calcom/cal.diy · error · UnauthorizedException
ApiKeysService - No API key provided
Error message
ApiKeysService - No API key provided
What it means
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.
Source
Thrown at apps/api/v2/src/modules/api-keys/services/api-keys.service.ts:28
import { createApiKeyHandler } from "@calcom/platform-libraries";
@Injectable()
export class ApiKeysService {
constructor(
private readonly apiKeysRepository: ApiKeysRepository,
private readonly config: ConfigService
) {}
async getRequestApiKey(request: ApiAuthGuardRequest) {
if (request.authMethod !== AuthMethods.API_KEY) {
throw new UnauthorizedException(
"ApiKeysService - This endpoint can only be accessed using an API key by providing 'Authorization: Bearer <apiKey>' header"
);
}
const apiKey = request.get("Authorization")?.replace("Bearer ", "");
if (!apiKey) {
throw new UnauthorizedException("ApiKeysService - No API key provided");
}
return apiKey;
}
async createApiKey(authUserId: number, createApiKeyInput: CreateApiKeyInput) {
if (createApiKeyInput.apiKeyDaysValid && createApiKeyInput.apiKeyNeverExpires) {
throw new BadRequestException(
"ApiKeysService -Cannot set both apiKeyDaysValid and apiKeyNeverExpires. It has to be either or none of them."
);
}
const defaultApiKeyDaysValid = 30;
const apiKeyExpiresAfterDays = createApiKeyInput.apiKeyDaysValid
? createApiKeyInput.apiKeyDaysValid
: defaultApiKeyDaysValid;
const apiKeyExpiresAt = DateTime.utc().plus({ days: apiKeyExpiresAfterDays }).toJSDate();
const apiKey = await createApiKeyHandler({
ctx: {View on GitHub (pinned to 176037d0af)
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.
Example fix
// before: header value incomplete
headers: { Authorization: 'Bearer ' }
// after: include the full API key
headers: { Authorization: `Bearer cal_${apiKey}` } Defensive patterns
Strategy: validation
Validate before calling
// Validate the Authorization header is complete before sending
const validateAuthHeader = (header: string | undefined): void => {
if (!header) throw new Error('Missing Authorization header');
const parts = header.split(' ');
if (parts[0] !== 'Bearer') throw new Error('Expected Bearer scheme');
if (!parts[1] || parts[1].length === 0) throw new Error('Authorization header has no token value');
}; Type guard
const hasValidBearerToken = (h: string | undefined): h is `Bearer ${string}` =>
typeof h === 'string' && h.startsWith('Bearer ') && h.slice(7).length > 0; Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- CustomThrottlerGuard - Invalid API Key
- ApiKeysService - This endpoint can only be accessed using an
- ApiKeysService - provided api key is not valid.
- ApiKeysService -Cannot set both apiKeyDaysValid and apiKeyNe
- This event type requires authentication. Please provide vali
AI-assisted analysis of calcom/cal.diy@176037d0af (2026-08-12).
Data as JSON: /api/errors/5f15bcbce60f81b1.
Report an issue: GitHub.