Error table

July 22, 2026 · View on GitHub

Every exception ChainWeaver raises is typed and inherits from ChainWeaverError. Each carries context attributes (e.g. tool_name, step_index, detail) so callers can inspect failures programmatically rather than parsing strings.

Stable diagnostic codes

Each exception class carries a stable code (e.g. CW-E006), exposed as a class attribute and on exc.code. The CLI prefixes it on error output (chainweaver: [CW-E006] …) and failing StepRecords carry it as error_code, so failures are greppable in logs/issues and --format json consumers can branch on the code instead of string-matching messages. Codes are append-only: once released they are never renumbered or reused. The tests/test_error_codes.py consistency check fails if any public exception lacks a code, a code is duplicated, or a code is missing from this table.

CodeExceptionWhen it is raised
CW-E000ChainWeaverErrorBase class for every error below.
CW-E001ToolNotFoundErrorA flow step references an unregistered tool.
CW-E002FlowNotFoundErrorThe requested flow (and optionally a specific version) is not registered.
CW-E003FlowAlreadyExistsErrorA registration would overwrite an existing (name, version) without overwrite=True.
CW-E004SchemaValidationErrorInput or output failed Pydantic validation at a step boundary.
CW-E005InputMappingErrorA step's input_mapping references a context key that does not exist.
CW-E006FlowExecutionErrorA tool callable raised an unexpected exception during execution.
CW-E007ToolDefinitionErrorThe @tool decorator (or Tool.from_flow) cannot construct a tool from the given inputs.
CW-E008ToolTimeoutErrorA Tool with timeout_seconds set exceeded the configured wall-clock cap.
CW-E009ToolOutputSizeErrorA Tool with max_output_size set returned output larger than the configured cap.
CW-E010DAGDefinitionErrorA DAGFlow has a cycle, a duplicate step_id, or an unknown dependency. The reason attribute is "duplicate_step_id", "unknown_dependency", or "cycle".
CW-E011FlowStatusErrorExecution attempted on a flow whose status is not ACTIVE (without force=True).
CW-E012FlowCancelledErrorA deadline passed or a CancellationToken was cancelled at a step boundary. Carries step_index, the partial result, and deadline_exceeded / token_cancelled flags.
CW-E013ContextKeyCollisionErrorA step output collides with an existing context key under on_context_collision="error".
CW-E014AsyncLaneUnsupportedErrorexecute_flow_async was given a flow using features the async lane does not support (conditional branching, decision_candidates). Composed sub-flows are supported on the async lane since #388.
CW-E015FlowCompositionErrorA composed flow's sub-flow references form a cycle, exceed max_composition_depth, or point to an unregistered flow. The reason attribute is "cycle", "max_depth_exceeded", or "unknown_flow".
CW-E016InvalidFlowVersionErrorA flow's version field is not a valid PEP 440 string.
CW-E017FlowSerializationErrorA .flow.yaml / .flow.json file is malformed, carries an incompatible format_version, or references an unresolvable class.
CW-E018CheckpointDriftErrorA resume_flow call detected schema drift since the snapshot was written.
CW-E019CheckpointerNotConfiguredErrorresume_flow was called on an executor without a configured checkpointer.
CW-E020CheckpointNotFoundErrorresume_flow could not locate the snapshot for the given trace_id.
CW-E021CheckpointVersionErrorA snapshot's snapshot_version has an incompatible MAJOR relative to the running library.
CW-E022PluginDiscoveryErrorAn entry-point plugin loader failed irrecoverably under strict=True.
CW-E023ContribErrorA first-party chainweaver.contrib.tools tool hit a deterministic contract violation.
CW-E024MCPErrorBase class for the chainweaver.mcp adapter / server error family.
CW-E025MCPSchemaConversionErrorAn MCP tool's JSON Schema cannot be projected to a Pydantic model.
CW-E026MCPToolInvocationErrorAn MCP tool invocation returned isError=True or the SDK call raised.
CW-E027MCPMetadataErrorServer-provided MCP tool metadata violates the configured MetadataPolicy.
CW-E028MCPSchemaDriftErrorA discovered MCP tool schema no longer matches its pin under on_drift="error".
CW-E029ApprovalDeniedErrorAn execution-time ApprovalCallback denied (or failed to approve) a gated step.
CW-E030SafetyCeilingErrorA step's side-effect level exceeds the executor's configured max_side_effect_level.
CW-E031DecisionCallbackErrorA DecisionCallback raised or returned a tool outside the step's decision_candidates.
CW-E032KernelInvocationErrorA KernelBackedExecutor could not dispatch a capability step.
CW-E033CostProfileErrorA cost estimate was requested for an unknown (provider, model) pair.
CW-E034OfflineLLMErrorAn offline, build-time LLM proposer could not use a completion (blank/invalid/malformed).
CW-E035AgentTraceImportErrorA coding-agent tool-use trace (JSONL) could not be imported.
CW-E036PredicateSyntaxErrorA conditional-branch predicate could not be parsed or evaluated.
CW-E037FlowBuilderErrorFlowBuilder.build() was called without a name or description.
CW-E038FuzzConfigErrorA fuzzing run could not be configured (no properties, runs < 1, no input source).
CW-E039AttestationInputErrorThe attestation input generator cannot synthesize a value for a schema field.
CW-E040FixtureStaleErrorA record_then_replay invocation could not be matched to a recording.
CW-E041OutputMappingErrorA step's output_mapping references an output key the tool did not produce.
CW-E042PromptBudgetExceededErrorAn offline proposer prompt exceeded its configured PromptBudget.max_tokens under overflow="error".
CW-E043LLMProviderErrorAn optional chainweaver.integrations.llm_* provider adapter could not complete an LLM call (retries exhausted, timeout, or unusable response).
CW-E044LLMBudgetExceededErrorA provider adapter would exceed its configured max_calls / max_cost_usd ceiling.
CW-E045FlowAuthenticationErrorA FlowServer authenticator returned None or raised; the call is refused before dispatch.
CW-E046RateLimitExceededErrorA FlowServer rate limiter declined the call.
CW-E047FlowAuthorizationErrorA FlowServer authorization callback denied the call (client-safe reason code only).
CW-E048OpenCodeAdapterErrorAn OpenCode plugin payload could not be normalized into a trace event, or a flow name has no name-safe characters.
CW-E049DecisionTimeoutErrorA decision callback exceeded the DecisionPolicy.timeout_s budget while on_timeout="error" was in effect.
CW-E050DecisionBudgetExceededErrorA flow exceeded its DecisionPolicy.max_decisions_per_flow budget.
CW-E051SchemaRefPolicyErrorThe active schema-ref policy rejected a "module:qualname" ref's module path before importing it (set_schema_ref_policy / SchemaRefAllowlist).
CW-E052GuardrailViolationErrorA registered guardrail_callback blocked a step at the input stage (content-safety / injection check).

Catching strategy

For most application code:

from chainweaver.exceptions import ChainWeaverError

try:
    result = executor.execute_flow(name, payload)
except ChainWeaverError as exc:
    log.exception("Flow %s failed", name, extra={"detail": getattr(exc, "detail", None)})
    raise

For drift-aware governance, catch CheckpointDriftError separately — it is the only error that indicates "the snapshot is intact but the world changed underneath it".