langfuse/langfuse · error · UnauthorizedError
${authCheck.error}
Error message
${authCheck.error} What it means
UnauthorizedError from authorizePromptRequestOrThrow when ApiAuthService.verifyAuthHeaderAndReturnScope reports an invalid key; the message is the underlying authCheck.error string (e.g., 'Invalid credentials'). Used by the public prompt API endpoints to gate requests.
Source
Thrown at web/src/features/prompts/server/utils/authorizePromptRequest.ts:15
import { ApiAuthService } from "@/src/features/public-api/server/apiAuth";
import { type NextApiRequest } from "next";
import { UnauthorizedError, ForbiddenError } from "@langfuse/shared";
import { prisma } from "@langfuse/shared/src/db";
import {
type AuthHeaderValidVerificationResult,
redis,
} from "@langfuse/shared/src/server";
export async function authorizePromptRequestOrThrow(req: NextApiRequest) {
const authCheck = await new ApiAuthService(
prisma,
redis,
).verifyAuthHeaderAndReturnScope(req.headers.authorization);
if (!authCheck.validKey) throw new UnauthorizedError(authCheck.error);
if (authCheck.scope.accessLevel !== "project")
throw new ForbiddenError(
`Access denied - need to use basic auth with secret key to ${req.method} prompts`,
);
if (!authCheck.scope.projectId) {
throw new ForbiddenError(`No valid projectId found for auth token`);
}
return authCheck as AuthHeaderValidVerificationResult & {
scope: { projectId: string; accessLevel: "project" };
};
}
View on GitHub (pinned to 59d92c7cf3)
Solutions
- Verify the API key pair exists and is active in project settings
- Send Authorization: Basic base64(pk:sk) for secret-key endpoints
- Check the underlying authCheck.error message for the precise cause
- Rotate and re-distribute keys if the old ones were revoked
Example fix
// before
fetch(url, { headers: { Authorization: `Bearer ${publicKey}` } });
// after
const creds = Buffer.from(`${publicKey}:${secretKey}`).toString('base64');
fetch(url, { headers: { Authorization: `Basic ${creds}` } }); Defensive patterns
Strategy: try-catch
Validate before calling
const token = Buffer.from(`${publicKey}:${secretKey}`).toString('base64');
if (!publicKey || !secretKey) throw new Error('API keys missing');
await fetch(url, { headers: { Authorization: `Basic ${token}` } }); Try / catch
try {
await api.prompts.list();
} catch (e) {
if (e.status === 401) { /* key invalid: verify/rotate keys in project settings */ }
if (e.status === 403) { /* scope wrong: use project secret key */ }
} Prevention
- Store pk/sk pairs together in a secrets manager
- Basic-auth encode as base64(pk:sk), never send raw
- Rotate keys atomically across all consumers
When it happens
Trigger: Hitting a public /api/public/prompts* endpoint with a missing, malformed, revoked, or non-existent API key in the Authorization header, causing validKey to be false.
Common situations: Wrong or rotated API keys in .env; Basic auth header not base64-encoded correctly; keys deleted after a security rotation; using org keys where project keys are required.
Related errors
- Missing projectId in scope. Are you using an organization ke
- Access denied: Bearer auth and org api keys are not allowed
- timeDimension and entityDimension are mutually exclusive
- Missing project ID
- UNAUTHORIZED
AI-assisted analysis of langfuse/langfuse@59d92c7cf3 (2026-08-27).
Data as JSON: /api/errors/74112beaaaa57c31.
Report an issue: GitHub.