amruthpillai/reactive-resume · error · Error
Unauthorized
Error message
Unauthorized
What it means
downloadResumePdf MCP tool resolves the caller from request headers via resolveUserFromRequestHeaders; if that returns null (no/invalid session) it throws a generic Error 'Unauthorized'. The tool does not rely on the transport's auth layer for this check — it explicitly verifies the user before signing the PDF download URL.
Source
Thrown at packages/mcp/src/tools.ts:167
T.getResumeAnalysis,
TOOL_META[T.getResumeAnalysis],
withErrorHandling("getting resume analysis", async ({ id }: { id: string }) => {
const analysis = await client.resume.analysis.getById({ id });
if (!analysis) return text("No saved analysis for this resume yet.");
return text(JSON.stringify(analysis, null, 2));
}),
);
// ── Download Resume PDF ────────��──────────────────────────────
server.registerTool(
T.downloadResumePdf,
TOOL_META[T.downloadResumePdf],
withErrorHandling("creating PDF download URL", async ({ id }: { id: string }) => {
const resume = await client.resume.getById({ id });
const user = await resolveUserFromRequestHeaders(requestHeaders);
if (!user) throw new Error("Unauthorized");
const signedUrl = createResumePdfDownloadUrl({ resumeId: id, userId: user.id });
return text(
JSON.stringify(
{
resumeId: id,
name: resume.name,
downloadUrl: signedUrl.url,
expiresAt: signedUrl.expiresAt,
expiresInSeconds: signedUrl.expiresInSeconds,
contentType: "application/pdf",
},
null,
2,
),
);
}),View on GitHub (pinned to 3a5b12e2a4)
Solutions
- Authenticate the MCP session (sign in via the web app and reuse the session, or pass a valid bearer token) before invoking downloadResumePdf.
- Ensure the MCP client forwards Cookie/Authorization headers to the server transport.
- On 401/Unauthorized, prompt re-authentication rather than retrying blindly.
- Verify the authBaseUrl and cookie domain match between the MCP endpoint and the auth session.
Example fix
// before: no auth header
await mcp.tools.call('downloadResumePdf', { id });
// after: forward session
await mcp.tools.call('downloadResumePdf', { id }, { headers: { cookie: sessionCookie } }); Defensive patterns
Strategy: try-catch
Validate before calling
// ensure the MCP client is authenticated before calling downloadResumePdf if (!await hasValidSession()) await promptReauth();
Type guard
function isUnauthorized(e: unknown): boolean {
return e instanceof Error && /unauthorized/i.test(e.message);
} Try / catch
try { await mcp.tools.call('downloadResumePdf', { id }); }
catch (e) {
if (isUnauthorized(e)) { await promptReauth(); return; }
throw e;
} Prevention
- Forward Cookie/Authorization headers through the MCP transport.
- Re-authenticate on session expiry instead of retrying.
- Verify authBaseUrl and cookie domain alignment.
When it happens
Trigger: Calling the MCP tool without a valid session cookie or Authorization header; an expired session; a transport that strips headers; the MCP server mounted without proxied auth headers.
Common situations: An MCP client (Claude/CLI/IDE) that didn't authenticate; a custom integration that forgot to forward credentials; session expired between listing resumes and requesting the download URL.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Application documents must be PDF files.
- AuthError
- FORBIDDEN
- BAD_REQUEST
- ${providerName} provider did not return an email address. Th
AI-assisted analysis of amruthpillai/reactive-resume@3a5b12e2a4 (2026-08-12).
Data as JSON: /api/errors/1bda1236129aaefa.
Report an issue: GitHub.