Troubleshooting¶
Common questions and diagnostic steps when working with Wardline.
Taint Assignment¶
"Why is my function getting UNKNOWN_RAW taint?"¶
The scanner assigns UNKNOWN_RAW when it has no evidence for a function's taint state. Check:
-
Is the function's module in
module_tiers? If not, add it: -
Does the function have a decorator? Decorators override
module_tiers. Add@external_boundary,@validates_shape, etc. as appropriate. -
At L3: Are callers decorated? L3 propagates taint through call chains, but unresolved call edges default to
UNKNOWN_RAW.
Use wardline explain <qualname> to see the taint resolution path:
"Why does the same rule give ERROR in one file and SUPPRESS in another?"¶
Severity depends on taint state, not the file. A function in an INTEGRAL module gets ERROR; the same pattern in an EXTERNAL_RAW module gets SUPPRESS.
Check the function's taint state:
Then look up the rule + taint state in the Severity Matrix.
Performance¶
"The scan is slow at L3"¶
L3 builds a full call graph. Reduce scan time by:
- Adding decorators: Resolved call edges are cheaper than unresolved ones
- Using L1/L2 in CI: Reserve L3 for nightly scans
- Scanning a subset:
wardline scan src/myapp/core/instead ofsrc/
Findings & Exceptions¶
"I have a finding on code I can't change"¶
Use an exception:
wardline exception add \
--rule PY-WL-004 \
--location "src/vendor/legacy.py::handle_error" \
--taint-state GUARDED \
--rationale "Third-party code, cannot modify" \
--elimination-path "Replace vendor library" \
--expires 2026-12-31
See Governance Walkthrough for the full process.
Configuration & Exit Codes¶
"Scan exits with code 2 but I don't see an error"¶
Exit code 2 is a configuration error. Run with --debug for details:
Common causes: - Missing wardline.yaml — see Getting Started - Stale wardline.resolved.json — re-run wardline resolve - Invalid overlay file — check wardline.overlay.yaml syntax
See Error Messages Reference for a full list.
"My exception stopped working after a code change"¶
When code changes, the AST fingerprint changes, and the exception becomes stale. The scanner emits GOVERNANCE-STALE-EXCEPTION.
Fix:
# Update fingerprints to match current code
wardline fingerprint update
# Refresh exceptions against updated fingerprints
wardline exception refresh
Diagnostics¶
"How do I see what the scanner thinks about a function?"¶
This shows: - The function's effective taint state - How that taint was determined (decorator, manifest, callgraph) - Which rules apply and their severity - Whether any exceptions cover it
"I added a decorator but the finding didn't go away"¶
Check: 1. Correct decorator? @validates_shape promotes to GUARDED, not ASSURED. If the caller expects ASSURED, you need @validates_semantic too. 2. Rejection path present? PY-WL-008 fires if the boundary function has no raise or guarded early return. 3. Right transition? The decorator's transition must match the data flow. @validates_shape expects EXTERNAL_RAW input. 4. Re-scanned? Scan results are not cached — re-run wardline scan.
Further Reading¶
- Error Messages Reference — error lookup table
- Rule Quick Reference — what each rule means
- CLI Reference — command options