{"record":{"id":"e72abe95b05bcb84","repo":"hcengineering/platform","slug":"unauthorized-e72abe","errorCode":null,"errorMessage":"Unauthorized","messagePattern":"Unauthorized","errorType":"http","errorClass":"ApiError","httpStatus":401,"severity":"error","filePath":"services/print/pod-print/src/server.ts","lineNumber":98,"sourceCode":"\n  const encodedToken = queryParams.token\n\n  if (encodedToken == null) {\n    return null\n  }\n\n  return encodedToken\n}\n\nconst extractToken = (headers: IncomingHttpHeaders, queryParams: any): string => {\n  try {\n    const token =\n      extractAuthorizationToken(headers.authorization) ??\n      extractQueryToken(queryParams) ??\n      extractCookieToken(headers.cookie)\n\n    if (token === null) {\n      throw new ApiError(401)\n    }\n\n    return token\n  } catch {\n    throw new ApiError(401)\n  }\n}\n\ntype AsyncRequestHandler = (\n  req: Request,\n  res: Response,\n  wsIds: WorkspaceIds,\n  wsLoginInfo: WorkspaceLoginInfo,\n  next: NextFunction\n) => Promise<void>\n\nconst handleRequest = async (\n  fn: AsyncRequestHandler,","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/services/print/pod-print/src/server.ts#L80-L116","documentation":"extractToken builds an auth token from the request by trying (in order) the Authorization header, a ?token= query parameter, and a cookie. If none yields a token it throws ApiError(401); the whole extraction is also wrapped in try/catch that rethrows ApiError(401) for any failure. This is the print service's generic 'no credentials supplied' 401.","triggerScenarios":"GET/POST to a print endpoint with no Authorization header, no 'token' query parameter, and no token cookie; an Authorization header present but malformed (e.g. 'Bearer' with no value, so split(' ')[1] is undefined → null via the catch path); empty token query param.","commonSituations":"Calling the print API from curl/Postman without copying the workspace token; a reverse proxy stripping the Authorization header or Cookie; frontend opening the print URL in a new tab where cookies aren't sent (third-party cookie blocking); token query param dropped by URL-encoding issues.","solutions":["Pass a valid workspace token: header 'Authorization: Bearer <token>', or '?token=<token>', or the session cookie","Check that the client actually stores/sends the token (inspect the outgoing request in devtools)","If behind a proxy, ensure Authorization and Cookie headers are forwarded","Fix the header format to 'Bearer <token>' (a bare token or missing space fails extraction)"],"exampleFix":"// before\ncurl 'https://print.example.com/print?kind=pdf'\n// after\ncurl -H 'Authorization: Bearer eyJhbGci...' 'https://print.example.com/print?kind=pdf'","handlingStrategy":"validation","validationCode":"const headers = { Authorization: `Bearer ${workspaceToken}` }\n// or: const url = `${printUrl}/print?token=${encodeURIComponent(workspaceToken)}&kind=pdf`\nif (!workspaceToken || workspaceToken.length < 20) {\n  throw new Error('Workspace token is missing or invalid; cannot call print service')\n}","typeGuard":"function hasToken(req: { headers: IncomingHttpHeaders; query: any }): boolean {\n  const auth = typeof req.headers.authorization === 'string' ? req.headers.authorization.split(' ')[1] : undefined\n  const q = typeof req.query?.token === 'string' ? req.query.token : undefined\n  const cookie = req.headers.cookie?.split(';').find(c => c.toLowerCase().includes('token'))?.split('=')[1]\n  return Boolean(auth ?? q ?? cookie)\n}","tryCatchPattern":"try {\n  const res = await fetch(printUrl, { headers: { Authorization: `Bearer ${token}` } })\n  if (res.status === 401) {\n    // refresh token / re-authenticate, then retry once\n    const fresh = await refreshWorkspaceToken()\n    return fetch(printUrl, { headers: { Authorization: `Bearer ${fresh}` } })\n  }\n  return res\n} catch (err) {\n  throw new Error(`Print request failed: ${(err as Error).message}`)\n}","preventionTips":["Always send 'Authorization: Bearer <token>' when calling the print service","Ensure proxies/gateways forward Authorization and Cookie headers","When opening print URLs in new tabs, append the token as a query parameter (cookies may be blocked)","Check devtools Network tab to confirm the token actually leaves the client"],"tags":["auth","http-401","token","print-service"],"backgroundTag":"missing-auth-token","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}