{"record":{"id":"5f15bcbce60f81b1","repo":"calcom/cal.diy","slug":"apikeysservice-no-api-key-provided","errorCode":null,"errorMessage":"ApiKeysService - No API key provided","messagePattern":"ApiKeysService - No API key provided","errorType":"exception","errorClass":"UnauthorizedException","httpStatus":401,"severity":"error","filePath":"apps/api/v2/src/modules/api-keys/services/api-keys.service.ts","lineNumber":28,"sourceCode":"\nimport { createApiKeyHandler } from \"@calcom/platform-libraries\";\n\n@Injectable()\nexport class ApiKeysService {\n  constructor(\n    private readonly apiKeysRepository: ApiKeysRepository,\n    private readonly config: ConfigService\n  ) {}\n\n  async getRequestApiKey(request: ApiAuthGuardRequest) {\n    if (request.authMethod !== AuthMethods.API_KEY) {\n      throw new UnauthorizedException(\n        \"ApiKeysService - This endpoint can only be accessed using an API key by providing 'Authorization: Bearer <apiKey>' header\"\n      );\n    }\n    const apiKey = request.get(\"Authorization\")?.replace(\"Bearer \", \"\");\n    if (!apiKey) {\n      throw new UnauthorizedException(\"ApiKeysService - No API key provided\");\n    }\n    return apiKey;\n  }\n\n  async createApiKey(authUserId: number, createApiKeyInput: CreateApiKeyInput) {\n    if (createApiKeyInput.apiKeyDaysValid && createApiKeyInput.apiKeyNeverExpires) {\n      throw new BadRequestException(\n        \"ApiKeysService -Cannot set both apiKeyDaysValid and apiKeyNeverExpires. It has to be either or none of them.\"\n      );\n    }\n\n    const defaultApiKeyDaysValid = 30;\n    const apiKeyExpiresAfterDays = createApiKeyInput.apiKeyDaysValid\n      ? createApiKeyInput.apiKeyDaysValid\n      : defaultApiKeyDaysValid;\n    const apiKeyExpiresAt = DateTime.utc().plus({ days: apiKeyExpiresAfterDays }).toJSDate();\n    const apiKey = await createApiKeyHandler({\n      ctx: {","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/calcom/cal.diy/blob/176037d0afbe572f870a3c702985e7cd83fe6c0c/apps/api/v2/src/modules/api-keys/services/api-keys.service.ts#L10-L46","documentation":"Thrown by ApiKeysService.getRequestApiKey when request.authMethod IS API_KEY but the Authorization header is missing or empty after stripping the 'Bearer ' prefix. The auth guard accepted the request as API-key-authenticated, but when the service extracts the actual key value from request.get('Authorization'), the result is null, undefined, or an empty string. This indicates a header parsing issue rather than a missing key.","triggerScenarios":"The Authorization header was stripped by a proxy, load balancer, or middleware before reaching the application. The header value is literally 'Bearer ' (with trailing space but no key). A case-sensitivity mismatch in the header name. The request was routed through a path that doesn't forward Authorization headers.","commonSituations":"A reverse proxy (nginx, Cloudflare) configured to strip or rename the Authorization header. A NestJS middleware or interceptor that consumes and removes the header. The client sending 'Authorization: Bearer' without the actual token value. ApiAuthGuard authenticating via a different mechanism (like a cookie or query param) while the authMethod is set to API_KEY by default or misconfiguration.","solutions":["Verify the raw Authorization header is present in the incoming request using browser dev tools or a network proxy (mitmproxy, Charles).","Check reverse proxy and load balancer configurations to ensure the Authorization header is forwarded unmodified.","Ensure the client sends the full header: 'Authorization: Bearer cal_<actual_key>' with no trailing whitespace after 'Bearer '.","Inspect the ApiAuthGuard/ApiAuthStrategy to confirm it reads from the same header field that getRequestApiKey expects."],"exampleFix":"// before: header value incomplete\nheaders: { Authorization: 'Bearer ' }\n\n// after: include the full API key\nheaders: { Authorization: `Bearer cal_${apiKey}` }","handlingStrategy":"validation","validationCode":"// Validate the Authorization header is complete before sending\nconst validateAuthHeader = (header: string | undefined): void => {\n  if (!header) throw new Error('Missing Authorization header');\n  const parts = header.split(' ');\n  if (parts[0] !== 'Bearer') throw new Error('Expected Bearer scheme');\n  if (!parts[1] || parts[1].length === 0) throw new Error('Authorization header has no token value');\n};","typeGuard":"const hasValidBearerToken = (h: string | undefined): h is `Bearer ${string}` =>\n  typeof h === 'string' && h.startsWith('Bearer ') && h.slice(7).length > 0;","tryCatchPattern":null,"preventionTips":["Always construct the Authorization header with a template literal: `Bearer ${apiKey}` to avoid missing the token.","Test the full request through a network proxy to confirm the Authorization header arrives intact at the server.","Configure reverse proxies to proxy_pass the Authorization header without stripping it.","In test suites, assert that the outgoing request includes a non-empty Authorization header."],"tags":["authentication","api-key","nestjs","api-v2","unauthorized","http-headers"],"backgroundTag":null,"analyzedSha":"176037d0afbe572f870a3c702985e7cd83fe6c0c","analyzedAt":"2026-08-12T19:12:41.464Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}