mastra-ai/mastra · error · HTTPException
Stored resource not found
Error message
Stored resource not found
What it means
After resolving a stored resource (e.g. an agent version), assertStoredResourceScope verifies the resource's metadata matches the caller's resolved resource scope. If the stored resource's scope metadata key does not equal the requested scope value, it throws HTTP 404 so the existence of out-of-scope resources is not revealed. This is an isolation guard against cross-tenant/cross-resource access.
Source
Thrown at packages/server/src/server/utils.ts:114
return metadata;
}
return {
...(metadata ?? {}),
[scope.metadataKey]: scope.value,
};
}
export function assertStoredResourceScope(
resource: StoredResourceLike | null | undefined,
scope: StoredResourceScope | undefined,
): void {
if (!resource || !scope) {
return;
}
if (resource.metadata?.[scope.metadataKey] !== scope.value) {
throw new HTTPException(404, { message: 'Stored resource not found' });
}
}
/**
* Check if a schema looks like a processor step schema.
* Processor step schemas are discriminated unions on 'phase' with specific values.
*/
function looksLikeProcessorStepSchema(schema: PublicSchema<unknown> | undefined): boolean {
if (!schema) return false;
try {
const jsonSchema = standardSchemaToJSONSchema(toStandardSchema(schema)) as Record<string, unknown> | undefined;
if (!jsonSchema) return false;
// Check for discriminated union pattern: anyOf/oneOf with phase discriminator
const variants = (jsonSchema.anyOf || jsonSchema.oneOf) as Array<Record<string, unknown>> | undefined;
if (!variants || !Array.isArray(variants)) return false;
View on GitHub (pinned to 75dd419e61)
Solutions
- Send the correct resource id (matching the one the resource was created with) in the request header
- Verify the stored record's metadata contains the expected scope key/value (fix data if it was migrated incorrectly)
- If the resource genuinely should be accessible, re-create it under the correct scope instead of editing metadata ad hoc
Example fix
// before curl -H 'x-mastra-resource-id: tenant-2' http://localhost:4111/api/agents/myAgent/versions/v1 // after curl -H 'x-mastra-resource-id: tenant-1' http://localhost:4111/api/agents/myAgent/versions/v1
Defensive patterns
Strategy: type-guard
Validate before calling
const scoped = versions.filter(v => v.metadata?.[scopeKey] === myResourceId); // only request ids present in `scoped`
Type guard
function isVersionInScope(v: { metadata?: Record<string, unknown> }, key: string, value: string): boolean {
return v.metadata?.[key] === value;
} Try / catch
try {
await activateVersion(id);
} catch (e) {
if (isHttp404(e)) { /* treat as not-visible-in-scope, do not retry */ }
else throw e;
} Prevention
- Treat 404 on scoped resources as 'not in your scope', never enumerate other scopes
- Keep scope metadata key in sync when copying records between environments
- Source version ids from scoped list responses only
When it happens
Trigger: Requesting an agent version whose metadata[scopeKey] differs from the caller's scope value — e.g. GET/ACTIVATE/RESTORE/DELETE on a version id created under a different resource id, or after the caller's resource-id header changed.
Common situations: Multi-tenant setups where a client switches tenants but caches old version ids; copying database records between environments without migrating the scope metadata key on stored resources; the caller sending the wrong x-mastra-resource-id for the resource they reference.
Related errors
- Version with id ${from} not found for agent ${agentId}
- Version with id ${to} not found
- Version with id ${to} not found for agent ${agentId}
- Stored resource scope is required
- Model "${modelId}" is not available. Available models: ${ids
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/f128f2054dc027ea.
Report an issue: GitHub.