{"record":{"id":"60f1c992d6db8a21","repo":"mastra-ai/mastra","slug":"authentication-required-60f1c9","errorCode":null,"errorMessage":"Authentication required","messagePattern":"Authentication required","errorType":"http","errorClass":"HTTPException","httpStatus":401,"severity":"error","filePath":"packages/server/src/server/handlers/stored-skill-favorites.ts","lineNumber":50,"sourceCode":" */\nexport const FAVORITE_STORED_SKILL_ROUTE = createRoute({\n  method: 'PUT',\n  path: '/stored/skills/:storedSkillId/favorite',\n  responseType: 'json',\n  pathParamSchema: storedSkillIdPathParams,\n  responseSchema: favoriteToggleResponseSchema,\n  summary: 'Favorite a stored skill',\n  description: 'Marks the stored skill as favorited by the calling user. Idempotent.',\n  tags: ['Stored Skills'],\n  requiresAuth: true,\n  requiresPermission: 'stored-skills:read',\n  handler: async ({ mastra, requestContext, storedSkillId }) => {\n    try {\n      await requireBuilderFeature(mastra, 'favorites');\n\n      const callerId = getCallerAuthorId(requestContext);\n      if (!callerId) {\n        throw new HTTPException(401, { message: 'Authentication required' });\n      }\n\n      const { skillStore, favoritesStore } = await getFavoritesContext(mastra);\n\n      const skill = await skillStore.getByIdResolved(storedSkillId);\n      if (!skill) {\n        throw new HTTPException(404, { message: `Stored skill with id ${storedSkillId} not found` });\n      }\n      assertStoredResourceScope(skill, await getStoredResourceScope(mastra, requestContext));\n\n      // Throws 404 if the caller cannot read the skill (private + not owner/admin).\n      assertReadAccess({ requestContext, resource: 'stored-skills', resourceId: storedSkillId, record: skill });\n\n      const result = await favoritesStore.favorite({\n        userId: callerId,\n        entityType: 'skill',\n        entityId: storedSkillId,\n      });","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/server/src/server/handlers/stored-skill-favorites.ts#L32-L68","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\nawait fetch(`${serverUrl}/stored/skills/${id}/favorite`, { method: 'PUT' });\n\n// after\nawait fetch(`${serverUrl}/stored/skills/${id}/favorite`, {\n  method: 'PUT',\n  headers: { Authorization: `Bearer ${token}` },\n});","handlingStrategy":"validation","validationCode":"if (!token || isTokenExpired(token)) {\n  await refreshToken(); // before calling the API\n}","typeGuard":null,"tryCatchPattern":"try {\n  return await api.put(`/stored/skills/${id}/favorite`);\n} catch (e) {\n  if (isHttpError(e) && e.status === 401) { redirectToLogin(); return null; }\n  throw e;\n}","preventionTips":["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"],"tags":["authentication","http-401","server","favorites"],"backgroundTag":"authentication-required","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}