mastra-ai/mastra · error · TripWire

Tripwire triggered in workflow ${workflow.id}

Error message

Tripwire triggered in workflow ${workflow.id}

What it means

When a sub-workflow run as a processor finishes with status 'tripwire', executeWorkflowAsProcessor re-throws it as a TripWire so the surrounding agent/processor pipeline handles it uniformly. The default message is used when the inner workflow's tripwire data carries no reason (e.g. an inner abort() without a reason).

Source

Thrown at packages/core/src/processors/runner.ts:585

        ...input,
        // Pass the processorStates map so workflow processor steps can access their state
        processorStates: this.processorStates,
        // Pass abortSignal so processors can cancel in-flight work
        abortSignal,
        agent: this.agent,
      } as ProcessorStepOutput,
      ...observabilityContext,
      requestContext,
      outputWriter: writer ? chunk => writer.custom(chunk) : undefined,
    });

    // Check for tripwire status - this means a processor in the workflow called abort()
    if (result.status === 'tripwire') {
      const tripwireData = (
        result as { tripwire?: { reason?: string; retry?: boolean; metadata?: unknown; processorId?: string } }
      ).tripwire;
      // Re-throw as TripWire so the agent handles it properly
      throw new TripWire(
        tripwireData?.reason || `Tripwire triggered in workflow ${workflow.id}`,
        {
          retry: tripwireData?.retry,
          metadata: tripwireData?.metadata,
        },
        tripwireData?.processorId || workflow.id,
      );
    }

    // Check for execution failure
    if (result.status !== 'success') {
      // Collect error details from the workflow result and failed steps
      const details: string[] = [];
      if (result.status === 'failed') {
        if (result.error) {
          details.push(result.error.message || JSON.stringify(result.error));
        }
        for (const [stepId, step] of Object.entries(result.steps)) {

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Fix the inner workflow: make every abort(reason) call include a message so it propagates.
  2. Catch this TripWire and inspect metadata/processorId to identify which inner step tripped.
  3. Check tripwireData?.retry — if false, don't retry; adjust the pipeline instead.
  4. Upgrade @mastra/core if inner tripwire reasons are set but lost during re-wrap (payload propagation bug).

Example fix

// before (inner processor)
abort();
// after
abort('Output failed safety check', { retry: false });
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await runProcessors(input);
} catch (e) {
  if (e?.name === 'TripWire' && e.processorId) {
    // tripwireData.retry === false means do not retry; inspect metadata
  } else throw e;
}

Prevention

When it happens

Trigger: runOutputProcessors / runInputProcessors / runProcessOutputStep / runProcessToolResult executes a workflow via executeWorkflowAsProcessor and result.status === 'tripwire' with no tripwireData.reason.

Common situations: Nesting a workflow as a processor where an inner step calls abort() without a message; wrapping workflows whose suspend/tripwire paths aren't wired with reasons; version drift where inner tripwire payload shape changed.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/63edc9b9064ac16c. Report an issue: GitHub.