mastra-ai/mastra · error · HTTPException
error.message (422 res body includes attempted/offendingLabe
Error message
error.message (422 res body includes attempted/offendingLabel for workflow label validation)
What it means
handleError maps a ModelNotAllowedError (code MODEL_NOT_ALLOWED, from @mastra/core/agent-builder/ee) thrown by agent-builder routes into an HTTPException with status 422 and a JSON body carrying code, message, allowed, attempted, and offendingLabel. The library throws this because the requested model (or model label) is not on the allowed model policy for the agent builder, so the request is semantically invalid even though the request shape is fine. The 422 body is structured so clients can show exactly which label/model was rejected and what is allowed.
Source
Thrown at packages/server/src/server/handlers/error.ts:107
}
// Helper to handle errors consistently
export function handleError(error: unknown, defaultMessage: string): never {
if (isModelNotAllowedError(error)) {
const body = {
error: {
code: error.code,
message: error.message,
allowed: error.allowed,
attempted: error.attempted,
offendingLabel: error.offendingLabel,
},
};
const res = new Response(JSON.stringify(body), {
status: 422,
headers: { 'content-type': 'application/json' },
});
throw new HTTPException(422, {
res,
message: error.message,
cause: error,
});
}
// A losing concurrent resume is a conflict on run state, not a malformed request, so it maps
// to 409 and clients can distinguish it from a 400/500 and re-read the run.
if (isWorkflowResumeAlreadyClaimedError(error)) {
throw new HTTPException(409, {
message: error.message,
stack: error.stack,
cause: error,
});
}
if (isWorkflowSchemaValidationError(error)) {
throw new HTTPException(400, {View on GitHub (pinned to 75dd419e61)
Solutions
- Read the 422 response body's error.attempted and error.offendingLabel plus error.allowed to see which model/label was rejected and switch the action to an allowed model.
- Update the agent-builder action's model field to one of the models in the allowed list from the error body.
- If the model should be permitted, adjust the server-side model policy/allowlist configuration to include that label or model ID.
- Check for a version mismatch between @mastra/server and @mastra/core (<1.34.0 lacks the agent-builder/ee subpath) and align versions.
Example fix
// before: run created with a disallowed model label
await client.getAgentBuilderActionRun(actionId, { model: 'gpt-4-internal' });
// after: use a model allowed by the policy (returned in error.allowed)
await client.getAgentBuilderActionRun(actionId, { model: 'openai/gpt-4o' }); Defensive patterns
Strategy: try-catch
Validate before calling
const allowedModels = new Set(['openai/gpt-4o', 'anthropic/claude-sonnet-4']);
if (!allowedModels.has(action.model)) {
throw new Error(`Model ${action.model} is not on the allowlist`);
} Type guard
function isModelNotAllowedBody(body: unknown): body is { error: { code: 'MODEL_NOT_ALLOWED'; allowed?: unknown; attempted?: unknown; offendingLabel?: string } } {
return !!body && typeof body === 'object' && (body as any).error?.code === 'MODEL_NOT_ALLOWED';
} Try / catch
try {
const run = await createAgentBuilderActionRun(actionId, input);
} catch (e) {
if (isModelNotAllowedBody(e.body)) {
console.warn(`Model '${e.body.error.offendingLabel}' rejected; allowed:`, e.body.error.allowed);
return pickAllowedModel(e.body.error.allowed);
}
throw e;
} Prevention
- Keep the client's model picker driven by the same allowlist the server enforces.
- Surface the 422 error.allowed list to users instead of a generic failure message.
- Re-sync actions' model fields after any model-policy change.
When it happens
Trigger: Calling LIST_AGENT_BUILDER_ACTIONS_ROUTE, GET_AGENT_BUILDER_ACTION_BY_ID_ROUTE, LIST_AGENT_BUILDER_ACTION_RUNS_ROUTE, GET_AGENT_BUILDER_ACTION_RUN_BY_ID_ROUTE, CREATE_AGENT_BUILDER_ACTION_RUN_ROUTE, or STREAM_AGENT_BUILDER_ACTION_ROUTE when the action references a model or label that fails the model allowlist policy (offendingLabel present in the 422 response body).
Common situations: A builder action was created with a model that a later model-policy change removed from the allowlist; an org restricts models by label (e.g. only 'small'/'large' tiers) and a run selects a disallowed label; bundled @mastra/server resolves against a core version whose agent-builder policy differs from what the UI expects.
Related errors
- Model not allowed by allowlist
- Invalid agent-builder action: ${actionId}. Valid actions are
- Invalid agent-builder action: ${actionId}
- ClaudeSDKAgent resumeData must include sessionId or continue
- CursorSDKAgent resumeData must include a message.
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/695c024bc6301744.
Report an issue: GitHub.