Skip to main content

Common failures

Current runs record lifecycle transitions in .loom/.runtime/runs/<run_id>/state.jsonl and contextual output and diagnostics in the adjacent events.jsonl. Start with loom logs <run_id> --state, then read loom logs <run_id> --json for the failed operation's IDs. MCP clients can use loom_read_run for states and loom_read_events with job_id or stream filters.

Match the error to a failure class, then follow the suggested check.

Not sure where to start? Begin with the Diagnostics ladder.


Schema validation failures (workflow YAML)​

Symptomloom check or loom run exits non-zero with "schema validation" errors referencing unknown fields, wrong types, or missing required keys.
Root causeWorkflow YAML does not match the expected schema version (field name, nesting, or type).
First stepFix the first reported error — later errors are often cascading.
loom check

Cross-reference the exact field name and type against Workflow schema v1. If the error only reproduces during execution, verify you are running loom check from the repo that contains .loom/workflow.yml and compare that file with any alternate path you pass to loom run.

Example error signatures (from schema validation tests):

WF_SCHEMA_V1 /include/0/local: set include.local to a normalized repository-relative .yml or .yaml path
WF_SCHEMA_V1 /.a/extends: resolve extends cycle by removing one extends edge: .a -> .b -> .a

See also: Syntax v1 · loom check · loom run


Docker provider issues (jobs using image:)​

SymptomJobs with image: fail to start, hang at startup, or fail during pull. Errors mention "cannot connect to Docker", "pull access denied", "no such image", or "exec format error".
Root causeDocker is not running or not reachable, the provider backend does not match your environment, or there is an image pull / auth / platform mismatch (e.g. arm64 vs amd64).
First stepVerify Docker is reachable from the shell where you run Loom.
docker version
docker info

If Docker is reachable, confirm which workspace mount mode Loom is using:

MethodExample
CLI flag--docker-workspace-mount bind_mount or --docker-workspace-mount ephemeral_volume
Environment variableLOOM_DOCKER_WORKSPACE_MOUNT=bind_mount

Read loom logs <run_id> --state --json for the failed job and its error field. Then inspect events.jsonl messages with that job_id; provider preparation can fail before any command starts. MCP loom_read_events can select the job directly.

Example provider failure (from Docker provider tests):

Cannot connect to the Docker daemon at unix:///var/run/docker.sock.

See also: Docker provider · loom run · Diagnostics ladder


Cache divergence quarantine (--cache-diff)​

SymptomA run with --cache-diff reports divergence and quarantines cache-hit keys (or refuses to trust a previously cached result).
Root causeLoom detected a correctness risk: a cached result does not match a recomputation. Common causes include nondeterministic scripts, untracked inputs, environment drift, or tool version changes.
First stepTreat this as a correctness signal, not "cache being flaky". Localize where divergence was detected.

Read the final workflow error in state.jsonl and the divergence diagnostic in events.jsonl. The cache-on execution uses the printed <run_id> directory; the cache-off baseline uses <run_id>-baseline-cache-off. Both directories contain the same two recording files. Quarantine entries, when present, are stored in .loom/.runtime/cache/v1/quarantine.json.

A comparison can report divergence even when both executions succeeded. Compare the recorded job outcomes and declared output files, and review changed inputs, tool versions and external state before changing keys or clearing quarantine. The two-file recording does not contain a structured comparison report.

See also: Cache concept · Cache workflow · loom run


Variable precedence surprises (unexpected values)​

SymptomA command behaves as if a variable has a different value than expected — wrong branch, wrong token, wrong flags. You set it in the workflow, but the step sees something else.
Root causeMultiple layers provide values (predefined, workflow, default, job, provider, or command-local variables), and a later layer overrides an earlier one.
First stepInspect what the failing step actually received — do not reason from memory.

Loom does not currently emit a dedicated "effective env" artifact. Add a temporary diagnostic line to your workflow to capture the resolved environment:

script:
- env | grep -E '^CI_|^LOOM_|^YOURPREFIX_' | sort
- <your real command>

Read loom logs <run_id> --json and locate events with the diagnostic command's job_id, step_id, command_id and stream: "stdout". Their message fields contain the printed output. MCP loom_read_events supports job_id and stream filters. Print only the nonsecret values needed for this diagnosis.

Compare the resolved value with the variable precedence rules. Host jobs also inherit the process environment; Docker jobs receive declared and predefined variables plus image defaults. Command-local assignments affect only the command they prefix.

See also: Variables concept · Variables workflow · loom run


Secrets resolution failures (SECRETS_*)​

SymptomA job fails before or during script execution with a SECRETS_* error code.
Root causeThe secret reference cannot be resolved — provider unavailable, ref malformed, entry missing, or required secret absent.
First stepRead the error code from CLI output or job events, then match it to the table below.
CodeMeaningFix
SECRETS_PROVIDER_UNAVAILABLEProvider unreachable, misconfigured, or authentication failedCheck the provider's configuration, credentials, and availability
SECRETS_REF_INVALIDMalformed or unsupported ref URIFix the ref value — check scheme and syntax
SECRETS_REF_NOT_FOUNDProvider resolved but entry/field does not existVerify env var is exported (env://) or entry path is correct (keepass://)
SECRETS_REQUIRED_MISSINGRequired secret could not be resolvedExport the env var, or set required: false if the secret is optional
SECRETS_UNSAFE_DEBUG_TRACECI_DEBUG_TRACE=true with file: false secretsDisable debug trace, or switch secrets to file: true

Find the failed job in loom logs <run_id> --state, then read its diagnostic messages in events.jsonl with the same job_id. Search message and state error text for the SECRETS_* code and any available provider or secret-name context. Known exact secret values are masked before recording; review excerpts before sharing them.

Example — required env-based secret where the var is not exported:

SECRETS_REQUIRED_MISSING: secret "DEPLOY_TOKEN" (env://DEPLOY_TOKEN) could not be resolved

Fix: export DEPLOY_TOKEN="your-value" before running Loom.

See also: Secrets error codes · Concepts → Secrets · Workflows → Secrets


Cannot locate the failing operation​

Read the state records before widening the output excerpt:

loom logs <run_id> --state
loom logs <run_id> --tail 30
loom logs <run_id> --json

Find the failed kind and its job_id, step_id and command_id when present. Match those IDs in event records. A provider failure can have a job ID without a command ID because the command never started. An interrupted run may lack a terminal state; use its last recorded states and events.

MCP loom_read_run returns all states. loom_read_events can filter by exact job_id and stream; tail and max_lines select a smaller excerpt. It returns total_events before limiting. Set max_lines to that total to read all matches.

See Diagnostics ladder and Runtime logs.


Still stuck?​

  1. Follow the full diagnostic flow: Diagnostics ladder
  2. Prepare a minimal report: What to share
  3. Include in your report:
    • The exact command you ran (including flags)
    • The run ID and relevant job, step and command IDs
    • The relevant state.jsonl records and a short reviewed events.jsonl excerpt
    • The validation receipt for a loom check failure, when available