Variables: Scalar, List, Dictionary, Environment, and Dynamic Values: Diagnostics, Failure Modes, and Production Practices
Diagnose variable failures by preserving evidence, separating source/priority/scope/type problems, and repairing the smallest ownership boundary instead of adding globals or retries.
Learning objectives
- Classify a variable incident as resolution, scope, type, mutation, path, environment, or secret-handling failure.
- Preserve first-failure output before changing values or rerunning a suite.
- Diagnose shadowing and static priority using explicit source evidence rather than guesswork.
- Repair shared mutable state without masking the failure through retries or global variables.
- Recognize when a Secret value can still leak through explicit unwrapping or external tools.
Current compatibility baseline. Verified
2026-08-31: Robot Framework 7.4.2 is the stable release used by this
chapter and requires Python 3.8+. Robot Framework 7.5b1 is a
pre-release and is not required. Native VAR has existed
since 7.0; scope=SUITES since 7.1; variable type
conversion such as ${count: int} is stable since 7.3;
and Secret variables are stable since 7.4.
1. Diagnostic sequence
When a variable-related test fails, preserve the original
output.xml, log.html, console command, and
non-sensitive environment/profile evidence. Then diagnose in this
order:
- Confirm Robot/Python versions and exact executed path.
- Confirm command-line variables and variable files supplied at startup.
- Inspect imports and Variable sections.
- Inspect local/test/suite/global runtime definitions and shadowing.
- Confirm object type and whether a container is shared.
- Inspect external environment/secret source without printing real secrets.
- Only after variable resolution is proven, investigate downstream library/system state.
This sequence avoids blaming a browser/API/database when the wrong value never reached that layer.
2. Failure mode: shadowing looks like overwrite
Suppose a suite default says ${REGION}=eu-west but one
keyword receives an argument named ${region}. Inside
the keyword the local argument wins. After the keyword returns, the
suite value is still intact. Logging only one layer can create the
false impression that the suite variable changed.
*** Variables ***
${REGION} eu-west
*** Test Cases ***
Shadowing Example
Report Region us-east
Should Be Equal ${REGION} eu-west
*** Keywords ***
Report Region
[Arguments] ${region}
Should Be Equal ${region} us-east
Repair is often naming/context clarity, not
Set Global Variable.
3. Failure mode: startup priority surprise
A CI wrapper may provide -v STAGE:staging while the
suite file says ${STAGE}=local. Editing the suite file
will not change the effective value because the higher-priority
command-line source still wins.
python -m robot --variable STAGE:staging --outputdir results/failure suites/
Preserve the exact invocation in the evidence packet. Configuration provenance is part of the test result.
4. Failure mode: numeric-looking strings
Environment variables are strings. The value "10" can
look numeric in a log but behave differently in comparisons,
arithmetic, or library type conversion. The repair is to establish a
typed boundary rather than scatter ad-hoc conversions through
keywords.
*** Test Cases ***
Broken Type Assumption
VAR ${workers} %{RF_WORKERS=10}
# ${workers} is a string here.
Repaired Boundary
VAR ${workers: int} %{RF_WORKERS=10}
Should Be True $workers >= 1
5. Failure mode: shared list mutation contaminates the next test
This is the chapter’s intentionally broken case. A suite-scoped list is mutated by the first test. The second test expects the original baseline and fails. Retrying the second test or increasing a timeout cannot repair the ownership bug.
*** Settings ***
Library Collections
*** Variables ***
@{BASE_ITEMS} alpha beta
*** Test Cases ***
Test A Mutates Shared State
Append To List ${BASE_ITEMS} gamma
Should Contain ${BASE_ITEMS} gamma
Test B Expects Baseline
Should Be Equal ${BASE_ITEMS} ${{['alpha', 'beta']}}
Expected failure: Test B sees gamma.
The diagnostic evidence is the first test’s mutation plus the
suite-owned container identity/lifetime.
Repair: keep an immutable/static baseline and copy it locally per test before mutation.
*** Test Cases ***
Isolated Test
${items}= Copy List ${BASE_ITEMS}
Append To List ${items} gamma
Should Be Equal ${BASE_ITEMS} ${{['alpha', 'beta']}}
6. Failure mode: variable file depends on the working directory
A relative --variablefile config/dev.py resolves from
the process invocation context. A local run from project root may
pass while CI starts in another directory. Diagnose the executed
working directory and command before adding arbitrary
PYTHONPATH hacks.
Prefer a documented project-root invocation or file-relative import conventions. The variable source should be reproducible from the same entry point used by CI.
7. Failure mode: treating Secret as encryption
A Secret can still leak when code deliberately accesses
.value, when a library unwraps it and logs the plain
value, or when another process receives it without compatible
redaction. Avoid TRACE-level diagnostics for sensitive paths unless
you know the complete logging chain.
*** Variables ***
${TOKEN: Secret} %{RF_TOKEN=FAKE_ONLY}
*** Test Cases ***
Unsafe Debugging Pattern
# Do not do this with real secrets:
# Log ${TOKEN.value}
The production repair is not “mask the screenshot later.” Keep acquisition, transport, library compatibility, result retention, and redaction as separate controls.
8. Performance: variables are rarely the first bottleneck
Variable parsing and lookup are usually negligible compared with
browser/API/database calls. Large dynamic variable files can add
import/setup cost, and enormous logged structures can inflate
output.xml, but measure before tuning. Do not replace
clear scoped values with global caches unless evidence shows a real
bottleneck and the state semantics remain correct.
9. Knowledge check
Why will editing a suite Variable section not override
-v STAGE:staging?
The individual command-line variable has higher startup priority.
Why is retrying Test B in the shared-list example a bad fix?
The failure is deterministic shared-state contamination; retrying does not restore ownership or the baseline.
What evidence should be preserved before changing a variable incident?
At minimum the original output/log/report, exact execution command, versions, and non-sensitive configuration-source evidence.
Can a Secret-aware Robot log protect a value that an external library prints after unwrapping it?
Not necessarily. Downstream code can still disclose the real value; Secret is not end-to-end encryption.
10. Summary and next step
Variable diagnosis starts with provenance and lifetime. Static priority, runtime shadowing, type conversion, mutable-object aliasing, working-directory assumptions, and secret handling each fail differently. Lesson 5 combines them in a checkpoint where you predict winners, verify them, and repair a shared-state bug while preserving evidence.
Further reading
- Robot Framework 7.4.2 User Guide — Variables — scalar/list/dictionary/environment syntax, creation mechanisms, priorities, scopes, typed conversion, and Secret values.
- Robot Framework 7.4.2 User Guide — Variable priorities and scopes — static priority and runtime scope rules.
- Robot Framework 7.4.2 User Guide — VAR syntax — local/test/task/suite/suites/global scope configuration.
- Robot Framework 7.4.2 User Guide — Variable type conversion — stable typed variable creation introduced in 7.3.
- Robot Framework 7.4.2 User Guide — Secret variables — masking semantics and security limitations introduced in 7.4.
- Robot Framework Style Guide — casing and scope-oriented naming conventions.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.