mastra-ai/mastra · error · Error

Model ${config.provider}/${config.modelId} is a metadata-onl

Error message

Model ${config.provider}/${config.modelId} is a metadata-only stub. The actual model instance should be resolved from the run registry.

What it means

resolveModel() in resolve-runtime.ts is a fallback used when the real model instance cannot be re-hydrated: it returns a metadata-only stub whose methods throw this descriptive error. Hitting it means the serialized model config (provider/modelId) was found in the run registry, but the actual MastraLanguageModel instance was never resolved from the run registry or Mastra instance.

Source

Thrown at packages/core/src/agent/durable/utils/resolve-runtime.ts:453

  } catch (error) {
    logger?.debug?.(`[DurableAgent:${agentId}] Failed to rebuild tools from Mastra for run ${runId}: ${error}`);
    return undefined;
  }
}

/**
 * Resolve the language model from serialized config.
 *
 * Note: This is a fallback when the model is not in the run registry.
 * The preferred approach is to store the actual model instance in the
 * run registry during preparation and retrieve it via runRegistry.getModel().
 *
 * This fallback returns a metadata-only stub that will fail the
 * isSupportedLanguageModel check with a descriptive error message.
 */
export function resolveModel(config: SerializableModelConfig, _mastra?: Mastra): MastraLanguageModel {
  const metadataError = () => {
    throw new Error(
      `Model ${config.provider}/${config.modelId} is a metadata-only stub. ` +
        `The actual model instance should be resolved from the run registry.`,
    );
  };

  return {
    provider: config.provider,
    modelId: config.modelId,
    specificationVersion: config.specificationVersion ?? 'v2',
    supportedUrls: {},
    doGenerate: metadataError,
    doStream: metadataError,
    __metadataOnly: true,
  } as MastraLanguageModel;
}

/**
 * Reconstruct the _internal (StreamInternal) object from available state

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Ensure resume/execution paths pass the Mastra instance to resolveModel so the real model can be looked up.
  2. Re-register the model under the same provider/modelId stored in the run registry.
  3. If a run is stale (model renamed/removed), start a new run instead of resuming it.
  4. Check the `__metadataOnly` hint in errors 1075 — it indicates this stub was reached.

Example fix

// before
const model = resolveModel(storedConfig);
// after
const model = resolveModel(storedConfig, mastra); // resolve real instance from registry
Defensive patterns

Strategy: type-guard

Validate before calling

const model = resolveModel(storedConfig, mastra);
if ((model as any).__metadataOnly) {
  throw new Error(`Model ${storedConfig.provider}/${storedConfig.modelId} is not registered; cannot resume run`);
}

Type guard

function isRealModel(m: unknown): m is MastraLanguageModel {
  return !!m && typeof m === 'object' && 'doStream' in m && !(m as any).__metadataOnly;
}

Try / catch

try {
  const model = resolveModel(config, mastra);
  assertRealModel(model);
} catch (e) {
  if (e instanceof Error && e.message.includes('metadata-only stub')) {
    logger.error(`Model ${config.provider}/${config.modelId} not in registry — re-register or start a new run`);
  }
  throw e;
}

Prevention

When it happens

Trigger: Resuming a durable run whose stored model config can't be mapped back to a real model — model registry miss, the provider/modelId no longer registered, or `mastra` not passed to resolveModel so no lookup is possible.

Common situations: Resuming runs after a deploy where model registration changed, renamed providers/models between versions, or resume code paths that lost the Mastra instance reference.

Related errors


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