RouterOS 7.24.4 – PPP profile scripts: :execute loses global variable context + on-down script appears snapshotted per session

Hello MikroTik Support,

we observed a reproducible scripting behavior on RouterOS 7.24.4 on CCR1016 devices after upgrading.

Environment

  • RouterOS: 7.24.4
  • Hardware: CCR1016-12G / CCR1016 series
  • PPPoE concentrator with scripts configured in PPP Profile on-up and on-down

Issue 1 – :execute from PPP profile script

The PPP profile script creates a global variable:

:global telegramMessage ("PPP [" . [/system identity get name] . "] " . $user . " = UP!")
:log info ("PPP UP MSG=[" . $telegramMessage . "]")
:execute "Send2Telegram"

The first log confirms that telegramMessage contains the expected value.

However, inside Send2Telegram:

:global telegramMessage
:log info ("TG TYPE=[" . [:typeof $telegramMessage] . "]")
:log info ("TG VALUE=[" . $telegramMessage . "]")
:log info ("TG LEN=[" . [:len $telegramMessage] . "]")

the variable is received as an empty string.

Replacing only:

:execute "Send2Telegram"

with:

/system script run Send2Telegram

immediately resolves the problem. The global variable is then available with its correct value and the same script works.

We reproduced this with both PPP on-up and on-down.

Issue 2 – PPP on-down appears to be stored with the active PPP session

During testing we discovered that changing the PPP profile on-down script does not change the script executed when an already-established PPP session disconnects.

Reproduction:

  1. PPP session is established while on-down contains script A.
  2. While that PPP session remains active, change the profile on-down to script B and Apply the configuration.
  3. Disconnect the existing PPP session.
  4. Script A is executed.
  5. Reconnect the same PPP user.
  6. Disconnect it again.
  7. Script B is now executed.

We confirmed this using unique log messages in scripts A and B.

We also observed old PPP sessions executing references to scripts that had already been removed from the current PPP profile configuration. After those clients reconnected, the old behavior disappeared.

This suggests that the on-down script is copied/bound to the PPP session when the session is established rather than evaluated from the current PPP profile when the session terminates.

Additional observation

Some sessions established with the previous script produce:

executing script
(ppp:<pppoe-USERNAME>) expected command name (line 1 column 1)

while newly established sessions using the modified profile execute correctly.

Questions

  1. Is the different execution context of :execute from PPP profile event scripts intentional in RouterOS 7.24.x?
  2. Was this behavior changed in 7.24 compared with previous RouterOS versions?
  3. Is /system script run <name> the recommended method when a PPP event script needs to pass global variables to another RouterOS script?
  4. Is the per-session snapshot/binding behavior of PPP on-down intentional and documented?

We can provide supout.rif, configuration excerpts and timestamped logs from the reproduction if required.

This isn't Mikrotik support . . . tey mikrotik.com/support for that . . .

This is a user group.

and this is another user with hidden profile (another bot?)

The scripts are poorly written for any version of RouterOS... it is just an AI hallucination.

While scripting is one of RouterOS’s most powerful features, treating it like a standard, forgiving Linux bash environment or ignoring basic principles—such as proper variable scoping, error handling, and Mikrotik's unique execution lifecycle—turns automation into a liability.

Below is an exhaustive breakdown of why ignoring RouterOS scripting fundamentals is highly dangerous, what the most common structural violations are, and how professional network administrators must approach automation to ensure stability.


1. The Anatomy of Failure: Common Violations of RouterOS Scripting Rules

When developers or administrators copy-paste unverified code or ignore the RouterOS documentation, they consistently make the same fundamental errors.

:stop_sign: Total Disregard for Variable Scoping (:local vs. :global)

RouterOS strictly separates local and global scopes. Failing to declare variables properly, or overusing global variables out of laziness, causes severe issues:

  • Memory Leaks and Value Pollution: Global variables persist in the system memory until a reboot or manual deletion. If a script reuses a global variable name without re-initializing it, it carries over stale data from previous executions, leading to unpredictable logic forks.
  • Race Conditions: If multiple scripts (or multiple instances of the same script running via scheduler) read and write to the same global variable simultaneously without locking mechanisms, the data becomes corrupted.

:stop_sign: Ignoring Execution Context and Environment Paths

MikroTik organized its CLI and scripting engine around a hierarchical menu structure (e.g., /ip/address, /interface/ethernet).

  • The Root Path Pitfall: Scripts often fail because they assume they are running from the root menu. If a script executes a command like add address=192.168.1.1 without explicitly declaring the path context (/ip/address add... or using /ip/address { ... }), the script will instantly crash if the environment shifts.
  • Version Incompatibility: Commands change between major RouterOS versions (especially between v6 and v7). Writing scripts without anchoring paths explicitly makes them incredibly fragile during system upgrades.

:stop_sign: Absence of Runtime Exception and Error Handling (:do / :on-error)

Network environments are dynamic; interfaces go down, DNS resolutions fail, and remote APIs become unreachable.

  • The Sudden Death Syndrome: By default, if a RouterOS script encounters an error (e.g., trying to fetch data from a URL that is offline using /tool/fetch), the entire script instantly terminates.
  • Without wrapping volatile operations in a :do { ... } on-error={ ... } block, the script provides no fallback, fails to log the error, and leaves the system in a half-configured, broken state.

2. The Cascading Consequences on Network Infrastructure

Ignoring these rules does not just result in a broken script; it directly impacts the hardware and the data plane.

Consequences Description Impact Level
CPU Spikes & Thread Starvation Poorly optimized loops (like checking a condition without a :delay) lock up the RouterOS management plane, causing 100% CPU utilization. Critical (Drops management access)
Flash Memory Degradation Scripts that constantly write temporary data to the system disk instead of memory (var or tmp) prematurely age the router's NAND/Flash storage through excessive write cycles. High (Hardware Failure)
Silent Failures Scripts that fail silently without writing to the /log system leave network engineers completely blind when debugging intermittent outages. Medium (Increased Troubleshooting Time)

3. The Professional Standard: How RouterOS Scripting Must Be Done

To write resilient automation on MikroTik hardware, scripts must adhere to strict engineering constraints:

  • Always Typecast Explicitly: RouterOS treats data types (strings, integers, IPs, arrays) strictly. Never assume the script engine will accurately guess a variable type. Use functions like :toip, :toarray, or :tonum to sanitize inputs.
  • Embrace the Delay: When interacting with hardware interfaces or waiting for an IP address lease, always implement brief :delay steps to allow the operating system to finish state transitions before the script queries them.
  • Log Everything Meaningfully: A well-behaved script utilizes /log info, /log warning, and /log error to create an audit trail. If a script makes a routing change, it must be documented in the system log.

Conclusion

Scripting in RouterOS is not an experimental sandbox; it is an extension of the network control plane. Writing code that flouts the basic architectural rules of MikroTik’s environment shows a fundamental lack of respect for network uptime. If an administrator is unwilling to master scoping, error trapping, and path hierarchy, they should rely on manual configuration or external tools like Ansible rather than deploying volatile, ticking time bombs directly onto production routers.