Troubleshooting
This guide helps recover from common issues when working with MCP Moira workflows.
Context Recovery After Session Archive
When a conversation is archived or compacted, the agent loses:
- Current execution ID (processId)
- Workflow step context
- Progress information
The workflow state persists on the MCP server - only the agent’s memory is lost.
Recovery Steps
- Find active executions:
session({ action: "executions" })Returns list of executions with status, workflow ID, and notes:
[ { "executionId": "abc-123", "workflowId": "development-flow", "status": "waiting", "note": "Feature: auth system", "currentNodeId": "implement-step" }]- Get current step without advancing:
session({ action: "current_step", executionId: "abc-123" })Returns the current directive and context:
{ "attemptId": "attempt-current", "directive": "Implement the feature...", "completionCondition": "Feature working and tested", "inputSchema": { ... }}- Continue workflow:
step({ processId: "abc-123", attemptId: "attempt-current", input: { ... } })Process ID Preservation
To help future recovery, save the process ID in your workspace:
# Create process-id.txt in feature directoryecho "abc-123" > ./feature-name/process-id.txtInclude in session archives:
- Feature name
- Process ID
- Current step description
Navigation Tools Reference
session - executions
Lists all active workflow executions for current user.
Call: session({ action: "executions" })
Filters:
status: Array of statuses -["waiting", "running", "completed", "failed"]workflowId: Filter by specific workflowsearch: Search in execution notes
Example with filters:
session({ action: "executions", status: ["waiting", "running"], search: "auth"})session - current_step
Retrieves current step directive without advancing the workflow.
Call: session({ action: "current_step", executionId: "..." })
Parameters:
executionId(required): Execution ID to check
Returns:
attemptId: Identity required to submit this exact current presentationdirective: What to docompletionCondition: Success criteriainputSchema: Response structure
session - execution_context
Gets full execution state including context variables.
Call: session({ action: "execution_context", executionId: "..." })
Parameters:
executionId(required): Execution ID to inspect
Returns:
executionId: Execution UUIDworkflowId: Workflow being executedstatus: Execution status (running, waiting, completed, failed)currentNodeId: Current node IDwaitingForInputNodeId: Node waiting for input (if any)note: Execution notecontext.variables: Context variablescontext.nodeStates: Node execution statescreatedAt,updatedAt,completedAt: Timestampserror: Error message (if failed)
Common Issues
“Process not found or expired”
Cause: Invalid or expired processId
Solution:
- Use
session({ action: "executions" })to find active executions - Use the correct executionId from the list
- Process IDs are UUIDs like
abc123-def456-...
“Execution is not waiting for input”
Cause: Trying to advance a completed or failed execution
Solution:
- Check execution status with
session({ action: "execution_context", executionId: "..." }) - Status must be
waitingto accept input - If
completedorfailed, start a new execution
Validation Errors on step()
Cause: Input doesn’t match inputSchema
Solution:
- Check
inputSchemafrom current step - Verify field names match exactly (case sensitive)
- Verify data types match (string vs number)
- Include all required fields
ATTEMPT_PROCESSING
Cause: Another caller still has a live claim on this exact step mutation.
Solution: Retry with the same Process ID, Step attempt ID, and input. Do not replace the attempt or alter the input.
ATTEMPT_STALE
Cause: The attempt no longer matches the current execution presentation and was rejected before handler work.
Solution: Automatically call session({ action: "current_step", executionId: "..." }), then
retry the intended submission once with the returned Step attempt ID. Do not reuse the stale ID.
ATTEMPT_CONFLICT
Cause: The attempt is already bound to a different input and the new submission was rejected before handler work.
Solution: Automatically call session({ action: "current_step", executionId: "..." }), discard
the conflicting attempt, and continue from the returned directive and input schema. Do not replay
the rejected input against the current presentation.
ATTEMPT_INVALID_OR_EXPIRED for a step
Cause: The step attempt is unavailable and was rejected before handler work. This recovery
applies only when the error explicitly directs the caller to current_step; an unavailable start
attempt has no current step to recover.
Solution: Automatically call session({ action: "current_step", executionId: "..." }), discard
the unavailable attempt, and continue from the returned directive and input schema.
ATTEMPT_OUTCOME_UNKNOWN
Cause: Moira could not prove whether a claimed mutation and its possible external effect completed.
Solution: Inspect the execution with session({ action: "current_step", executionId: "..." })
and the relevant external system. Do not automatically retry the mutation.
CURRENT_PRESENTATION_STALE
Cause: The persisted live attempt belongs to a different node, or to a continuation surface the current definition no longer has: something the paused node declares about what it does changed, or a registry entry for a global variable it declares as an input did. It cannot be safely rebound to the current execution. A change that does not reach that surface does not produce this state — a version or tag bump, an edit to another node, or a cosmetic change to the paused node itself all leave the run usable.
Solution: Do not retry the old attempt. Call
session({ action: 'diagnose', executionId: '...' }), which names which facts of the paused step
changed, whether its node still exists, and anything else standing between the run and its next
step. Then repair the run with
session({ action: 'recover', executionId: '...', nodeId: '<node to resume from>', variableValues: { ... } }),
which re-presents it at the node you name with the values that step needs and returns a fresh Step
attempt ID to continue from. Name a node a run can wait on — an agent-directive, teleport,
materialize, lock or subgraph node; any other node is refused, because resuming there would run the
workflow forward instead of repairing it. The run comes to rest on the node you name and never goes
past it, but a lock node creates its lock and sends its approval code when the run arrives there,
and a subgraph node enters its child — choose one of those as the target only when you want that.
Recovery is also refused unless the run really cannot continue, and refused for a run that is already
finished or cancelled, which stays that way; a refusal changes nothing.
Agent Forgets Workflow Context
Cause: Session was archived/compacted
Solution:
- Check for process-id.txt in workspace
- Use
session({ action: "current_step" })to get context - Remind agent: “Continue workflow {processId}”
Seeing [[UNDEFINED_VARIABLE]] in a directive at runtime
Cause: A referenced variable was unresolved when the directive was rendered. Three causes:
- The variable is not declared in
variableRegistry. - The variable is declared but has no
defaultand was not yet written by an upstream node before the directive used it. - A bare
{{...}}was placed into data the agent returned viastep(), and that data was later interpolated into a directive (template-in-data). Returned data values are literal — they are not re-scanned as templates.
The engine logs a warning naming the residual placeholder and the executionId.
Solution:
- Declare the variable in
variableRegistrywith adefault. - Ensure an upstream node writes the variable (via
globalInputs) before its first use. - Never echo
{{...}}into data you return fromstep()— keep templates only in static node fields.
Recovery Scenarios
Scenario: Resume After Interruption
User: Continue working on the auth feature
Agent:1. session({ action: "executions", search: "auth" }) → Found: executionId: "abc-123", status: "waiting"
2. session({ action: "current_step", executionId: "abc-123" }) → attemptId: "attempt-current", directive: "Implement login endpoint"
3. [Does the work]
4. step({ processId: "abc-123", attemptId: "attempt-current", input: { result: "done" } })Scenario: Find Lost Process ID
User: What workflows am I running?
Agent:1. session({ action: "executions" }) → Lists all active executions with notes
2. session({ action: "execution_context", executionId: "abc-123" }) → Shows full context including variablesScenario: Check Why Workflow Stuck
Agent:1. session({ action: "execution_context", executionId: "abc-123" }) → status: "waiting", currentNodeId: "validation-step"
2. session({ action: "current_step", executionId: "abc-123" }) → Shows what the workflow is waiting forRelated Documentation
- MCP Agent Guide - Tool usage basics
- MCP Tools Reference - Full tool documentation