VFX-D-1203¶
Title¶
PlaceholderUsedBeforeDefinition
Explanation¶
A {placeholder} token is interpolated by a step that runs before anything provides its value.
A name resolves if a root variables entry declares it (those are loaded into the shared variable
context before the first step runs) or if an earlier step captures it. A step's own capture
does not count for that same step: a capture is produced by running the step, so it is available
from the next step onwards.
This rule is order-aware, which is what distinguishes it from VFX-D-1204. The same token in the
same suite is a defect in step 0 and correct in step 2 — the finding says "not yet", not "never".
Engine reserved forms — {svc::<name>.<field>}, {conn::<name>}, {__outcome::...} — are never
reported: they resolve from the environment rather than from the variable context.
Host-owned listener and receiver names count as defined everywhere in the suite, not just after
the step that names them. A webhook-listen.* step's listener and a trace-expect.* step's
receiver name infrastructure the engine stands up, and the engine stages each one at its plain
Vars key precisely so an earlier step can interpolate it — which is how the canonical webhook suite
is written: step 0 registers a callback URL as {callbacks}, and step 1 is the
webhook-listen.http with listener: callbacks. That suite is correct and is not reported.
A script.* step's code and file are not scanned for placeholders. C# spells its own string
interpolation with the same braces, so $"order {id} created" inside a script body is not a suite
placeholder: the engine never interpolates a script body against the variable context — the script
reads Vars["id"] itself. The same exclusion applies to summary.placeholders, so the digest and
this rule always agree about what a placeholder is.
Reported as a warning in the semanticDiagnostics channel, located at the step that used the
token rather than at the individual field, because the fix is a decision about step ordering.
Common causes¶
- Two steps written in the wrong order — the step that consumes an id placed before the step that creates it.
- A step interpolating a value it captures itself, in the same step.
- A typo in either the placeholder or the capture key, so the two never match (
{orderID}vs a capture namedorderId— matching is case-sensitive). - A placeholder left over from a step that was deleted or moved.
Fixes¶
- Move the step that captures the value above the step that uses it.
- Or declare the name under the root
variablesblock if it is a constant rather than a captured value. - Check the capture key's exact spelling against the placeholder —
validate_suite'ssummary.capturesandsummary.placeholderslist both sides.