mastra-ai/mastra · error · HTTPException
Authentication required
Error message
Authentication required
What it means
The PUT /stored/skills/:storedSkillId/favorite route requires an authenticated caller identity. After the builder 'favorites' feature gate passes, the handler calls getCallerAuthorId(requestContext); if it cannot resolve an author id from the request context it throws HTTPException 401 'Authentication required'. The route is declared requiresAuth: true, so the request also must carry valid auth.
Source
Thrown at packages/server/src/server/handlers/stored-skill-favorites.ts:50
*/
export const FAVORITE_STORED_SKILL_ROUTE = createRoute({
method: 'PUT',
path: '/stored/skills/:storedSkillId/favorite',
responseType: 'json',
pathParamSchema: storedSkillIdPathParams,
responseSchema: favoriteToggleResponseSchema,
summary: 'Favorite a stored skill',
description: 'Marks the stored skill as favorited by the calling user. Idempotent.',
tags: ['Stored Skills'],
requiresAuth: true,
requiresPermission: 'stored-skills:read',
handler: async ({ mastra, requestContext, storedSkillId }) => {
try {
await requireBuilderFeature(mastra, 'favorites');
const callerId = getCallerAuthorId(requestContext);
if (!callerId) {
throw new HTTPException(401, { message: 'Authentication required' });
}
const { skillStore, favoritesStore } = await getFavoritesContext(mastra);
const skill = await skillStore.getByIdResolved(storedSkillId);
if (!skill) {
throw new HTTPException(404, { message: `Stored skill with id ${storedSkillId} not found` });
}
assertStoredResourceScope(skill, await getStoredResourceScope(mastra, requestContext));
// Throws 404 if the caller cannot read the skill (private + not owner/admin).
assertReadAccess({ requestContext, resource: 'stored-skills', resourceId: storedSkillId, record: skill });
const result = await favoritesStore.favorite({
userId: callerId,
entityType: 'skill',
entityId: storedSkillId,
});View on GitHub (pinned to 75dd419e61)
Solutions
- Attach valid credentials to the request (Authorization: Bearer <token> or the server's configured auth mechanism)
- Refresh or re-obtain an expired token before retrying
- Verify the server's auth configuration resolves the principal to an author id (user/identity mapping)
- Ensure the request actually flows through the auth middleware so requestContext contains the caller identity
Example fix
// before
await fetch(`${serverUrl}/stored/skills/${id}/favorite`, { method: 'PUT' });
// after
await fetch(`${serverUrl}/stored/skills/${id}/favorite`, {
method: 'PUT',
headers: { Authorization: `Bearer ${token}` },
}); Defensive patterns
Strategy: validation
Validate before calling
if (!token || isTokenExpired(token)) {
await refreshToken(); // before calling the API
} Try / catch
try {
return await api.put(`/stored/skills/${id}/favorite`);
} catch (e) {
if (isHttpError(e) && e.status === 401) { redirectToLogin(); return null; }
throw e;
} Prevention
- Attach auth headers via a shared fetch/axios interceptor
- Refresh tokens proactively before they expire
- Verify the auth provider maps users to author ids used by requestContext
When it happens
Trigger: Calling PUT /stored/skills/:id/favorite without an Authorization header/session, with an expired or malformed token, or with credentials that don't map to a caller author id in requestContext (getCallerAuthorId returns undefined).
Common situations: Scripts or CI hitting the API with no auth configured; token expired between calls; internal service calls that bypass the auth middleware so requestContext has no user; misconfigured auth provider so the authenticated principal has no authorId.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- ${validationResult.error || 'invalid_token'}
- No session
- Session expired
- Storage is not configured
- Favorites storage domain is not available
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/60f1c992d6db8a21.
Report an issue: GitHub.