mastra-ai/mastra · error · Error
Agent step "${params.id}" uses a legacy v1 model but does no
Error message
Agent step "${params.id}" uses a legacy v1 model but does not implement streamLegacy(). What it means
When createStep wraps an Agent whose model is a legacy v1-style model, the workflow needs the agent to expose streamLegacy() to run it in the evented workflow engine. If the agent reports a legacy model but lacks a streamLegacy() implementation, this Error is thrown because there is no compatible execution path.
Source
Thrown at packages/core/src/workflows/evented/workflow.ts:602
...observabilityContext,
requestContext,
onFinish: (result: any) => {
handleFinish(result);
void safeOnFinish((agentOptions as any)?.onFinish, result, logger);
},
abortSignal,
});
fullStream = modelOutput.fullStream;
textPromise = modelOutput.text;
} else {
// V1 model path: use .streamLegacy() for backwards compatibility
let resolveText: (value: string) => void;
textPromise = new Promise(resolve => {
resolveText = resolve;
});
if (typeof params.streamLegacy !== 'function') {
throw new Error(`Agent step "${params.id}" uses a legacy v1 model but does not implement streamLegacy().`);
}
const legacyResult = await params.streamLegacy((inputData as { prompt: string }).prompt, {
...(agentOptions ?? {}),
...observabilityContext,
requestContext,
onFinish: (result: any) => {
handleFinish(result);
resolveText!(result.text);
void safeOnFinish((agentOptions as any)?.onFinish, result, logger);
},
abortSignal,
});
fullStream = legacyResult.fullStream;
}
if (abortSignal.aborted) {
return abort() as TStepOutput;View on GitHub (pinned to 75dd419e61)
Solutions
- Upgrade @mastra/core (and the agent's model adapter) so the Agent implements streamLegacy, or better, use a v2 model so the legacy path is not needed.
- If using a custom/mock agent, add a streamLegacy(prompt, options) method returning the legacy stream result.
- Verify all Mastra packages resolve to a single version (pnpm why @mastra/core) to avoid duplicate/mismatched installs.
Example fix
// before
const fakeAgent = { id: 'a', model: legacyModel, stream: async () => {} } as any;
createStep(fakeAgent);
// after
const fakeAgent = {
id: 'a',
model: legacyModel,
stream: async () => {},
streamLegacy: (prompt, opts) => legacyModel.doStream(prompt, opts),
} as any;
createStep(fakeAgent); Defensive patterns
Strategy: type-guard
Validate before calling
if (typeof (agent as any).streamLegacy !== 'function') {
throw new Error(`Agent ${agent.id ?? '?'} lacks streamLegacy; upgrade @mastra/core or use a v2 model`);
} Type guard
const supportsLegacyStream = (a: any): a is { streamLegacy: Function } & Record<string, unknown> =>
a != null && typeof a.streamLegacy === 'function'; Try / catch
try {
const step = createStep(agent);
} catch (e) {
if (e instanceof Error && e.message.includes('does not implement streamLegacy()')) {
// surface version-mismatch guidance
}
throw e;
} Prevention
- Keep all @mastra/core-related packages on one version (pnpm why / lockfile check).
- Prefer v2-compatible models so the legacy path is never used.
- In tests, mock agents should implement both stream and streamLegacy.
When it happens
Trigger: Passing an Agent to createStep(agent) where the agent's model is detected as legacy (v1 LanguageModel) and typeof agent.streamLegacy !== 'function' — typically an agent built with an older adapter or a hand-rolled Agent-like object missing streamLegacy.
Common situations: Mixing @mastra/core versions (agent built against older core without streamLegacy) inside a newer evented workflow; custom Agent subclasses overriding internals; mock/stub agents in tests that only implement stream.
Related errors
- RUN_EXPERIMENT_TARGET_FAILED_TO_GENERATE_RESULT
- Agent '${entry.agentId}' not found for workflow step '${entr
- Dynamic workflow references agent "${entry.agentId}" which i
- Invalid email or password
- Workflow ${workflowId} not found
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/d45ad7732410cb88.
Report an issue: GitHub.