{"record":{"id":"3bf4313f20a527c7","repo":"immich-app/immich","slug":"not-authenticated-with-an-api-key","errorCode":null,"errorMessage":"Not authenticated with an API Key","messagePattern":"Not authenticated with an API Key","errorType":"http","errorClass":"ForbiddenException","httpStatus":403,"severity":"error","filePath":"server/src/services/api-key.service.ts","lineNumber":59,"sourceCode":"    }\n\n    const key = await this.apiKeyRepository.update(auth.user.id, id, { name: dto.name, permissions: dto.permissions });\n\n    return this.map(key);\n  }\n\n  async delete(auth: AuthDto, id: string): Promise<void> {\n    const exists = await this.apiKeyRepository.getById(auth.user.id, id);\n    if (!exists) {\n      throw new BadRequestException('API Key not found');\n    }\n\n    await this.apiKeyRepository.delete(auth.user.id, id);\n  }\n\n  async getMine(auth: AuthDto): Promise<ApiKeyResponseDto> {\n    if (!auth.apiKey) {\n      throw new ForbiddenException('Not authenticated with an API Key');\n    }\n\n    const key = await this.apiKeyRepository.getById(auth.user.id, auth.apiKey.id);\n    if (!key) {\n      throw new BadRequestException('API Key not found');\n    }\n\n    return this.map(key);\n  }\n\n  async getById(auth: AuthDto, id: string): Promise<ApiKeyResponseDto> {\n    const key = await this.apiKeyRepository.getById(auth.user.id, id);\n    if (!key) {\n      throw new BadRequestException('API Key not found');\n    }\n    return this.map(key);\n  }\n","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/immich-app/immich/blob/199723261c6ffa897fec8ccdaea6359e39c37cc3/server/src/services/api-key.service.ts#L41-L77","documentation":"Thrown by ApiKeyService.getMine as a ForbiddenException (HTTP 403) when auth.apiKey is falsy. The endpoint's contract is to return the key currently making the request, which is only meaningful when the caller authenticated with an API key. Session-based (cookie/JWT) callers have no apiKey on the auth context.","triggerScenarios":"GET /api-keys/me while authenticated with a web session cookie or a bearer JWT instead of an API key (`x-api-key` header). Any non-API-key auth scheme will trip this.","commonSituations":"Browser dev tools hitting the endpoint while logged in via session; SDK client initialized with email/password auth instead of an API key; mixing session and key auth in one client.","solutions":["Call this endpoint only with API-key authentication (x-api-key header)","For session-authenticated callers, use GET /api-keys to list keys instead of /api-keys/me","Check the client's auth method before invoking getMine"],"exampleFix":"// before\nconst me = await sdk.getMyApiKey({ sessionCookie }); // 403\n// after\nconst me = await sdk.getMyApiKey({ apiKey: 'sk_...' }); // x-api-key","handlingStrategy":"validation","validationCode":"// Only call /api-keys/me when authenticated with an API key\nif (!authMethod || authMethod !== 'x-api-key') {\n  // use the list endpoint instead for session auth\n  const keys = await sdk.getAllApiKeys();\n  return;\n}\nconst me = await sdk.getMyApiKey();","typeGuard":"function isApiKeyAuth(auth: { apiKey?: unknown }): auth is { apiKey: { id: string; permissions: string[] } } {\n  return !!auth?.apiKey && typeof (auth.apiKey as any).id === 'string';\n}","tryCatchPattern":null,"preventionTips":["Reserve GET /api-keys/me for API-key-authenticated clients only","Use GET /api-keys for session-authenticated callers","Track the active auth method in the client and branch endpoint selection"],"tags":["api-key","authentication","authorization","nestjs","forbidden"],"backgroundTag":null,"analyzedSha":"199723261c6ffa897fec8ccdaea6359e39c37cc3","analyzedAt":"2026-08-12T04:54:27.085Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}