hcengineering/platform · error · ApiError

Unauthorized

Error message

Unauthorized

What it means

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.

Source

Thrown at services/print/pod-print/src/server.ts:98

  const encodedToken = queryParams.token

  if (encodedToken == null) {
    return null
  }

  return encodedToken
}

const extractToken = (headers: IncomingHttpHeaders, queryParams: any): string => {
  try {
    const token =
      extractAuthorizationToken(headers.authorization) ??
      extractQueryToken(queryParams) ??
      extractCookieToken(headers.cookie)

    if (token === null) {
      throw new ApiError(401)
    }

    return token
  } catch {
    throw new ApiError(401)
  }
}

type AsyncRequestHandler = (
  req: Request,
  res: Response,
  wsIds: WorkspaceIds,
  wsLoginInfo: WorkspaceLoginInfo,
  next: NextFunction
) => Promise<void>

const handleRequest = async (
  fn: AsyncRequestHandler,

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Pass a valid workspace token: header 'Authorization: Bearer <token>', or '?token=<token>', or the session cookie
  2. Check that the client actually stores/sends the token (inspect the outgoing request in devtools)
  3. If behind a proxy, ensure Authorization and Cookie headers are forwarded
  4. Fix the header format to 'Bearer <token>' (a bare token or missing space fails extraction)

Example fix

// before
curl 'https://print.example.com/print?kind=pdf'
// after
curl -H 'Authorization: Bearer eyJhbGci...' 'https://print.example.com/print?kind=pdf'
Defensive patterns

Strategy: validation

Validate before calling

const headers = { Authorization: `Bearer ${workspaceToken}` }
// or: const url = `${printUrl}/print?token=${encodeURIComponent(workspaceToken)}&kind=pdf`
if (!workspaceToken || workspaceToken.length < 20) {
  throw new Error('Workspace token is missing or invalid; cannot call print service')
}

Type guard

function hasToken(req: { headers: IncomingHttpHeaders; query: any }): boolean {
  const auth = typeof req.headers.authorization === 'string' ? req.headers.authorization.split(' ')[1] : undefined
  const q = typeof req.query?.token === 'string' ? req.query.token : undefined
  const cookie = req.headers.cookie?.split(';').find(c => c.toLowerCase().includes('token'))?.split('=')[1]
  return Boolean(auth ?? q ?? cookie)
}

Try / catch

try {
  const res = await fetch(printUrl, { headers: { Authorization: `Bearer ${token}` } })
  if (res.status === 401) {
    // refresh token / re-authenticate, then retry once
    const fresh = await refreshWorkspaceToken()
    return fetch(printUrl, { headers: { Authorization: `Bearer ${fresh}` } })
  }
  return res
} catch (err) {
  throw new Error(`Print request failed: ${(err as Error).message}`)
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Related errors


AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29). Data as JSON: /api/errors/e72abe95b05bcb84. Report an issue: GitHub.