Skip to content

Troubleshooting

Most problems surface when a spec loads, never in the middle of a run (RULES R4): harnessweaver spec validate and harnessweaver doctor show the same errors the app would raise. Every error is a taxonomy error with a stable code (Outcomes and errors). The messages below are real ones.

When a spec doesn't load

LockViolation

LockViolation: observability.capture_content is locked by org://acme-baseline@1.1.0 (.../acme-baseline.yaml)
(lock 'observability.capture_content'); it can't be changed (R1)

A later layer (your spec or an overlay) changes a path an org profile locked. Remove the change, or restate the same value. If the org's value is wrong for you, the fix is a change to the baseline, by its owners. harnessweaver spec explain --path <path> shows the lock and the layer that set it. Remember an overlay can trigger this even when the base spec doesn't: validate every -e you deploy.

BoundViolation

BoundViolation: budgets.per_run.max_usd = 8.0 (set by harness.yaml) is above the maximum 5 that
org://acme-baseline@1.1.0 (.../acme-baseline.yaml) allows (R10)

A number or duration is outside a profile's bounds. Nothing is clamped, so lower the value. Task budgets are also checked against the budgets.per_run bounds. The same error comes from a per-run override that raises a limit, or overrides a field the task doesn't list in budget.overridable.

LevelTooLow

LevelTooLow: app reaches L1 but its risk tier 'customer_facing' requires L2.
Missing: policy.rules has at least one rule

The baseline requires a higher adoption level for your metadata.risk_tier. Add what the message lists; harnessweaver doctor shows the same under next level. See Adoption levels.

UnknownProvider

UnknownProvider: no installed plugin provides namespace 'nope'; install one that does,
or list an in-repo module under plugins.local
UnknownProvider: no Guardrail provider named 'pii.regexx' in plugin 'harnessweaver'; it provides:
grounded.citations, injection.heuristic, llm.judge, pii.regex, regex.deny, secrets.scan, size.limit, topic.deny

A use: names something that isn't installed, or is misspelled. Install the plugin package (uv add ...) or add the module to plugins.local; harnessweaver plugin list shows what is installed. In TypeScript, a provider that exists only in Python fails the same way: pass the plugin to load({ plugins }), use a TypeScript provider, or declare the guard where: sidecar.

PluginNotAllowed

PluginNotAllowed: plugin namespace 'nope' isn't in plugins.allow (acme, anthropic, openai, otel, pydantic_ai)

The org baseline's plugins.allow doesn't list the namespace. Ask the baseline's owners to review and allow the plugin.

PluginConflict and IncompatibleContract

Two installed packages claim the same namespace, or a plugin was built for a contract range this core doesn't support. harnessweaver plugin list shows each plugin's namespace, version, contract range and compatibility; uninstall one of the conflicting packages, or upgrade the plugin.

UnreachableHook

A runner or adapter can't reach a hook point the baseline or the budget needs: for example a budget with model limits and an adapter that can't see model calls. Choose a runner or adapter that reaches it (harnessweaver doctor lists each task's runner and its hooks), or move the control.

Other SpecErrors

Message Cause Fix
unknown or misplaced key(s) guardrail for a Harness document (allowed: ...) A misspelled or misplaced top-level key Use one of the listed keys
provider pii.regex settings: entitys: Extra inputs are not permitted A misspelled provider setting Check the provider's settings in its module page
guard topic.deny can't run at stage 'context'; it supports input, output A guard at a stage its provider doesn't support Move it, or pick another provider
policy.rules[rule#1].when: unexpected 'end of expression' at position 13 A cel-lite expression that doesn't compile Fix the expression (cel-lite); rule#1 is the generated id of the first rule without one
invalid YAML: duplicate key 'models' A key repeated in one map (YAML 1.2 rule) Merge the two entries
routing.r: default 'b' is not one of the options A router's default outside its options Add it to options or change it
can't find profile 'org://missing@^1'; see HARNESSWEAVER_PROFILE_PATH An org profile not on the search path, or no version matching the range Set HARNESSWEAVER_PROFILE_PATH or --profile-dir; check the file name (<name>.yaml or <name>@<version>.yaml) and metadata.version
profiles extend each other in a cycle Two profiles extending each other Break the cycle
tools.manifests: no file matches 'tools/*.tool.yaml' under ... A manifest glob that matches nothing Check the path, relative to the spec
a code tool must name a sandbox, such as monty (S4) A transport: code manifest without sandbox Add sandbox: monty (and install harnessweaver-monty)
observability.exporter: otlp needs observability.configure_sdk: true; ... observability.exporter set while configure_sdk is false Set configure_sdk: true (with harnessweaver-otel), or configure OpenTelemetry in the app and drop exporter

When a run is blocked

The run's RunResult.error.details.code (or the RunBlocked error's details["code"] in a session) says which control stopped it; the trace says why.

Code Means Look at
policy_denied A deny rule matched (at run.start or governor step 3) The harness.policy or harness.governor note names the rule
budget_exceeded A limit was reached; details.limit names it The harness.budget notes; raise the task's budget within bounds, or reduce calls
deadline_exceeded The run's deadline passed The deadline in the task budget and budgets.per_run
guard_blocked A guard blocked The harness.guard note names the guard and its finding types; consider shadow mode while tuning
validation_failed The output was still invalid after the last repair The repair notes list the problems; improve the prompt or output type, or raise max_repairs
retry_exhausted model.after asked for a second retry The middleware returning Retry
model_not_allowed The alias isn't in models.allowed_aliases Use an allowed alias
max_steps The direct runner's tool loop ran out of model calls runner: { use: direct, max_steps: ... }
tool_unknown, manifest_required A tool with no registration or manifest tools.manifests, or the tools given in code
tool_not_offered The model of a direct task called a registered tool the task doesn't offer Add it to the task's tools if the task should have it; otherwise look for what steered the model
digest_mismatch A tool's definition changed since its digest was pinned Review the change, then harnessweaver tools pin
schema_invalid The arguments don't match the tool's input_schema The note names the failing locations
trifecta A tool with egress after untrusted and private data entered the run, with trifecta: block The run's labels and sources; whether the tool needs egress
rate_limited The manifest's rate_limit was reached The limit, or the caller's behavior
approval_rejected A human rejected the call -
middleware_error, middleware_timeout A closed middleware raised or timed out The failure trace event names the middleware and the exception type
retry_not_supported A Retry where it isn't honored Return Block or Escalate there instead

Other surprises

Symptom Cause Fix
ProviderError from every model call in tests Test mode: live providers refuse to call out Use a scripted model or a cassette (Testing)
RunResult.cost_known is false; max_usd never trips No cost report and no price for the model Run behind a gateway that reports cost, or add models.prices
No spans in your backend No OpenTelemetry SDK is configured Configure it in the app, or observability.configure_sdk: true with harnessweaver-otel and an endpoint
No logs at all HarnessWeaver is silent by default logger.enable("harnessweaver")
A Suspend became escalated A standalone session, a wrapped agent or TypeScript can't wait for a person Run the work as a task (harness.run) when it needs approvals
An instrumented client raises on stream=True Streaming through instrument() is planned Use the non-streaming call, or s.generate(stream=True) in a session
A guard fires on content it shouldn't Guards are blunt instruments Put it in shadow mode, collect evidence with eval run, tune its settings or its action
harnessd answers 401 A missing or wrong Authorization: Bearer token The client's token and harnessd's --token-env
harnessd won't start No token in HARNESSD_TOKEN (or the --token-env variable), or a spec that doesn't load Set the token; run spec validate on the same spec and overlay

When in doubt, run uv run harnessweaver doctor harness.yaml -e <env> and read the trace (harnessweaver.testing.render_trace(result)).