{"record":{"id":"c22811fb167fdb94","repo":"immich-app/immich","slug":"invalid-share-key","errorCode":null,"errorMessage":"Invalid share key","messagePattern":"Invalid share key","errorType":"http","errorClass":"UnauthorizedException","httpStatus":401,"severity":"error","filePath":"server/src/services/auth.service.ts","lineNumber":500,"sourceCode":"  }\n\n  private getCookieOauthState(headers: IncomingHttpHeaders): string | null {\n    const cookies = parse(headers.cookie || '');\n    return cookies[ImmichCookie.OAuthState] || null;\n  }\n\n  private getCookieCodeVerifier(headers: IncomingHttpHeaders): string | null {\n    const cookies = parse(headers.cookie || '');\n    return cookies[ImmichCookie.OAuthCodeVerifier] || null;\n  }\n\n  async validateSharedLinkKey(key: string | string[]): Promise<AuthDto> {\n    key = Array.isArray(key) ? key[0] : key;\n\n    const bytes = Buffer.from(key, key.length === 100 ? 'hex' : 'base64url');\n    const sharedLink = await this.sharedLinkRepository.getByKey(bytes);\n    if (!this.isValidSharedLink(sharedLink)) {\n      throw new UnauthorizedException('Invalid share key');\n    }\n\n    return { user: sharedLink.user, sharedLink };\n  }\n\n  async validateSharedLinkSlug(slug: string | string[]): Promise<AuthDto> {\n    slug = Array.isArray(slug) ? slug[0] : slug;\n\n    const sharedLink = await this.sharedLinkRepository.getBySlug(slug);\n    if (!this.isValidSharedLink(sharedLink)) {\n      throw new UnauthorizedException('Invalid share slug');\n    }\n\n    return { user: sharedLink.user, sharedLink };\n  }\n\n  private isValidSharedLink(\n    sharedLink?: AuthSharedLink & { user: AuthUser | null },","sourceCodeStart":482,"sourceCodeEnd":518,"githubUrl":"https://github.com/immich-app/immich/blob/199723261c6ffa897fec8ccdaea6359e39c37cc3/server/src/services/auth.service.ts#L482-L518","documentation":"UnauthorizedException (HTTP 401) thrown by validateSharedLinkKey when no valid shared link matches the supplied key bytes. The key is decoded (hex if length 100, else base64url) and looked up via sharedLinkRepository.getByKey; if no row returns or the link is expired/has no user, isValidSharedLink fails.","triggerScenarios":"Any shared-link-capable route called with x-immich-share-key (or ?key=) carrying a wrong, revoked, or expired key. Also when the key format is incorrect (not 100 hex chars or valid base64url) so the decoded bytes do not match any stored hash.","commonSituations":"User copied an old share key after the owner regenerated it; share link expired (expiresAt passed); link was deleted; trailing characters or URL-encoding issues corrupted the key; client used the share slug as a key.","solutions":["Obtain the current share key from the owner or regenerate the shared link in the share dialog.","If the link has expired, ask the owner to extend expiresAt or create a new share.","Verify the key is sent verbatim (watch for URL-decoding by the client) and as the right header (x-immich-share-key) or query (?key=).","Confirm 100-char hex keys are sent without spaces/newlines."],"exampleFix":"// before\nawait axios.get('/shared-links/me', { headers: { 'x-immich-share-key': 'typos-and-trailing-' } });\n// -> 401 Invalid share key\n\n// after\nawait axios.get('/shared-links/me', { headers: { 'x-immich-share-key': correctKey.trim() } });","handlingStrategy":"validation","validationCode":"function looksLikeValidShareKey(key: string): boolean {\n  return /^([0-9a-fA-F]{100}|[A-Za-z0-9_-]+)$/.test(key.trim());\n}","typeGuard":"function isPlausibleShareKey(value: unknown): value is string {\n  return typeof value === 'string' && value.trim().length > 0 && looksLikeValidShareKey(value);\n}","tryCatchPattern":"try {\n  await axios.get('/shared-links/me', { headers: { 'x-immich-share-key': key } });\n} catch (e) {\n  if (e.response?.status === 401) {\n    showShareExpiredOrRevoked();\n  } else throw e;\n}","preventionTips":["Trim and validate the key format before sending.","Treat 401 'Invalid share key' as expired/revoked and prompt for a new share.","Send the key in the documented header (x-immich-share-key) or query (?key=), not both."],"tags":["auth","shared-link","unauthorized","nestjs","immich"],"backgroundTag":null,"analyzedSha":"199723261c6ffa897fec8ccdaea6359e39c37cc3","analyzedAt":"2026-08-12T04:54:27.085Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}