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

  1. 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.
  2. If using a custom/mock agent, add a streamLegacy(prompt, options) method returning the legacy stream result.
  3. 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

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


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