mastra-ai/mastra · error · Error

Unknown step entry type: ${JSON.stringify(_exhaustive)}

Error message

Unknown step entry type: ${JSON.stringify(_exhaustive)}

What it means

This is the exhaustive-switch default in `serializeEntry`: TypeScript's `never` check catches a `StepFlowEntry` variant the serializer doesn't recognize — usually a newly added entry type the switch wasn't updated for, or a corrupted/foreign object injected into the `stepFlow`. The thrown message embeds the JSON of the unexpected entry for diagnosis.

Source

Thrown at packages/core/src/workflows/dynamic/serialize.ts:103

    }
    case 'loop': {
      const predicate = entry.predicate;
      if (!predicate || typeof predicate !== 'object') {
        throw new Error(
          `Loop step "${getSingleStepEntryId(entry.step)}" cannot be stored: closure predicates do not round-trip. Use the declarative form ({ predicate: {...} }).`,
        );
      }
      return {
        type: 'loop',
        step: serializeSingleEntry(entry.step),
        serializedCondition: entry.serializedCondition,
        loopType: entry.loopType,
        predicate,
      };
    }
    default: {
      const _exhaustive: never = entry;
      throw new Error(`Unknown step entry type: ${JSON.stringify(_exhaustive)}`);
    }
  }
}

function serializeSingleEntry(entry: SingleStepEntry): SerializedSingleStepEntry {
  if (entry.type === 'agent') {
    const options = pickSerializableStepOptions(entry.options, entry.id, 'agent');
    const outputSchema = extractStructuredOutputJsonSchema(entry.options, entry.id);
    return {
      type: 'agent',
      id: entry.id,
      agentId: entry.agentId,
      description: entry.agent?.description,
      ...(outputSchema ? { outputSchema } : {}),
      ...(options ? { options } : {}),
    };
  }
  if (entry.type === 'tool') {

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Log/inspect the embedded JSON (`entry.type`) to identify the unknown variant.
  2. Update @mastra/core to a version whose serializer supports the entry type, or downgrade the producer of the graph.
  3. If the entry is hand-built, construct it via the library's supported entry factories instead.
  4. If you maintain core, extend the switch with a case for the new entry type so exhaustiveness holds.
Defensive patterns

Strategy: type-guard

Validate before calling

const KNOWN_TYPES = new Set(['step','agent','tool','mapping','sleep','sleepUntil','parallel','foreach','conditional','loop']);
for (const e of stepFlow) {
  if (!e || !KNOWN_TYPES.has(e.type)) throw new Error(`Unknown step entry type: ${JSON.stringify(e)}`);
}

Type guard

const isKnownEntryType = (e: unknown): e is StepFlowEntry =>
  !!e && typeof e === 'object' && KNOWN_TYPES.has((e as any).type);

Try / catch

try {
  storable = toStorableGraph(stepFlow);
} catch (e) {
  if (/Unknown step entry type/.test(e.message)) {
    const detail = JSON.parse(e.message.slice(e.message.indexOf(':') + 1));
    // inspect detail.type; fix producer or upgrade @mastra/core
  } else throw e;
}

Prevention

When it happens

Trigger: Calling `toStorableGraph` with a `stepFlow` array containing an entry whose `type` is not one of step/agent/tool/mapping/sleep/sleepUntil/parallel/foreach/conditional/loop — e.g. hand-assembled entries, entries from a newer core version, or data loaded from storage with an unknown type.

Common situations: Upgrading @mastra/core and feeding old persisted graphs forward; custom tooling that constructs StepFlowEntry objects manually; type assertions (`as any`) hiding a malformed entry from the compiler.

Related errors


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