mastra-ai/mastra · error · HTTPException
Authentication required
Error message
Authentication required
What it means
The favorites toggle handler derives the caller's author id from requestContext via getCallerAuthorId. When the request carries no authenticated caller identity, the handler throws HTTPException 401 'Authentication required'. Favoriting is a per-user action, so an anonymous caller cannot be served.
Source
Thrown at packages/server/src/server/handlers/stored-agent-favorites.ts:50
*/
export const FAVORITE_STORED_AGENT_ROUTE = createRoute({
method: 'PUT',
path: '/stored/agents/:storedAgentId/favorite',
responseType: 'json',
pathParamSchema: storedAgentIdPathParams,
responseSchema: favoriteToggleResponseSchema,
summary: 'Favorite a stored agent',
description: 'Marks the stored agent as favorited by the calling user. Idempotent.',
tags: ['Stored Agents'],
requiresAuth: true,
requiresPermission: 'stored-agents:read',
handler: async ({ mastra, requestContext, storedAgentId }) => {
try {
await requireBuilderFeature(mastra, 'favorites');
const callerId = getCallerAuthorId(requestContext);
if (!callerId) {
throw new HTTPException(401, { message: 'Authentication required' });
}
const { agentStore, favoritesStore } = await getFavoritesContext(mastra);
const agent = await agentStore.getById(storedAgentId);
if (!agent) {
throw new HTTPException(404, { message: `Stored agent with id ${storedAgentId} not found` });
}
assertStoredResourceScope(agent, await getStoredResourceScope(mastra, requestContext));
// Throws 404 if the caller cannot read the agent (private + not owner/admin).
assertReadAccess({ requestContext, resource: 'stored-agents', resourceId: storedAgentId, record: agent });
const result = await favoritesStore.favorite({
userId: callerId,
entityType: 'agent',
entityId: storedAgentId,
});View on GitHub (pinned to 75dd419e61)
Solutions
- Attach valid credentials (Authorization header or session cookie) to the request
- Refresh or re-obtain the auth token if expired
- Confirm auth middleware is registered and runs before the favorites route
- Verify getCallerAuthorId's expected requestContext key is populated by your auth provider
Example fix
// before
fetch('/api/stored-agents/123/favorite', { method: 'PUT' })
// after
fetch('/api/stored-agents/123/favorite', {
method: 'PUT',
headers: { Authorization: `Bearer ${token}` },
credentials: 'include',
}) Defensive patterns
Strategy: try-catch
Validate before calling
// Before calling the API const token = getSessionToken(); if (!token) redirectToLogin();
Type guard
function hasCallerIdentity(ctx: unknown): ctx is { callerAuthorId: string } {
return typeof ctx === 'object' && ctx !== null && typeof (ctx as any).callerAuthorId === 'string' && (ctx as any).callerAuthorId.length > 0;
} Try / catch
try {
await api.toggleFavorite(agentId);
} catch (e) {
if (e.status === 401) { refreshToken(); redirectToLogin(); }
else throw e;
} Prevention
- Attach Authorization headers/cookies in a shared API client wrapper
- Proactively refresh tokens before expiry
- Require auth middleware on all mutating routes
When it happens
Trigger: PUT /stored/agents/:storedAgentId/favorite (and other favorites routes) without an authenticated user in requestContext — missing/invalid auth token, expired session, or auth middleware not populating the caller identity.
Common situations: Calling the API from a script without attaching credentials; expired JWT/session cookie; auth middleware misconfigured or bypassed on the playground/server proxy; builder feature enabled but auth not wired up.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- invalid API key or insufficient permissions
- Session expired. Run: mastra auth login
- Bearer token required
- Invalid email or password
- State token has expired
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/c8d8d38469cd16fa.
Report an issue: GitHub.