{"record":{"id":"a1952075b5123410","repo":"immich-app/immich","slug":"authentication-required","errorCode":null,"errorMessage":"Authentication required","messagePattern":"Authentication required","errorType":"exception","errorClass":"UnauthorizedException","httpStatus":401,"severity":"error","filePath":"server/src/services/auth.service.ts","lineNumber":267,"sourceCode":"    const apiKey = (headers[ImmichHeader.ApiKey] || queryParams[ImmichQuery.ApiKey]) as string;\n\n    if (shareKey) {\n      return this.validateSharedLinkKey(shareKey);\n    }\n\n    if (shareSlug) {\n      return this.validateSharedLinkSlug(shareSlug);\n    }\n\n    if (session) {\n      return this.validateSession(session, headers);\n    }\n\n    if (apiKey) {\n      return this.validateApiKey(apiKey);\n    }\n\n    throw new UnauthorizedException('Authentication required');\n  }\n\n  getMobileRedirect(url: string) {\n    return `${MOBILE_REDIRECT}?${url.split('?', 2)[1] || ''}`;\n  }\n\n  async authorize(dto: OAuthConfigDto) {\n    const { oauth } = await this.getConfig({ withCache: false });\n\n    if (!oauth.enabled) {\n      throw new BadRequestException('OAuth is not enabled');\n    }\n\n    return await this.oauthRepository.authorize(\n      oauth,\n      this.resolveRedirectUri(oauth, dto.redirectUri),\n      dto.state,\n      dto.codeChallenge,","sourceCodeStart":249,"sourceCodeEnd":285,"githubUrl":"https://github.com/immich-app/immich/blob/f48d4b332127ad365ba256108799ca8f571d2dd5/server/src/services/auth.service.ts#L249-L285","documentation":"Thrown by validate() when a request carries neither a session/access token nor an API key, so the caller cannot be identified. The service rejects with 401 because no authentication credential exists at all.","triggerScenarios":"validate() sees no accessToken in cookies/headers and no apiKey header or query param; both credential paths are undefined.","commonSituations":"Omitting the x-api-key header in scripts/curl; expired or cleared Immich session cookie; reverse proxy stripping Cookie/x-api-key headers; machine clients with no credentials configured.","solutions":["Add the x-api-key header (or apikey query param) with a valid API key for machine access","Log in via web/mobile to obtain a session cookie for user flows","Ensure the reverse proxy forwards Cookie and x-api-key headers","Check that your HTTP client actually attaches the configured credentials"],"exampleFix":"// before\nfetch('/api/albums')\n// after\nfetch('/api/albums', { headers: { 'x-api-key': process.env.IMMICH_API_KEY } })","handlingStrategy":"validation","validationCode":"if (!apiKey && !sessionCookie) throw new Error('Provide x-api-key header or a logged-in session before calling the API');","typeGuard":"const isAuthed = (r: { headers: Record<string, string> }) => Boolean(r.headers['x-api-key'] || r.headers['cookie']);","tryCatchPattern":"try { await api.request() } catch (e) { if (e.status === 401 && /Authentication required/.test(e.message)) { /* attach credentials and retry once */ } throw e; }","preventionTips":["Always attach the API key in machine clients","Avoid proxies that strip auth headers","Refresh sessions before long-running jobs"],"tags":["auth","unauthorized","api-key","session"],"backgroundTag":"authentication-required","analyzedSha":"f48d4b332127ad365ba256108799ca8f571d2dd5","analyzedAt":"2026-09-15T07:20:19.675Z","contentChangedAt":"2026-09-15T07:20:19.675Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}