hcengineering/platform · error
Token error
Error message
Token error
What it means
The withToken Express middleware rejects a request with 401 'Token error' when no bearer token can be extracted from the request headers via extractToken. This middleware is a gateway guard: without a token the request never reaches the route handler. It exists so that downstream code can assume req.token is always set.
Source
Thrown at services/payment/pod-payment/src/middleware.ts:30
// See the License for the specific language governing permissions and
// limitations under the License.
//
import type { NextFunction, Request, Response } from 'express'
import { extractToken, getAccountClient } from '@hcengineering/server-client'
import { AccountRole, systemAccountUuid } from '@hcengineering/core'
import { Token } from '@hcengineering/server-token'
import type { LoginInfo, LoginInfoRequest, WorkspaceLoginInfo } from '@hcengineering/account-client'
export interface RequestWithAuth extends Request {
token?: Token
loginInfo?: LoginInfo | WorkspaceLoginInfo | LoginInfoRequest
}
export const withToken = (req: RequestWithAuth, res: Response, next: NextFunction): void => {
const token = extractToken(req.headers)
if (token === undefined || token == null) {
res.status(401).json({ message: 'Token error' }).end()
return
}
req.token = token
next()
}
export const withAdmin = (req: RequestWithAuth, res: Response, next: NextFunction): void => {
if (req.token === undefined || req.token == null) {
res.status(401).json({ message: 'Token error' }).end()
return
}
if (req.token.account !== systemAccountUuid && req.token.extra?.admin !== 'true') {
res.status(401).json({ message: 'Admins only' }).end()
return
}
next()
}
View on GitHub (pinned to 63e28dc964)
Solutions
- Add a valid 'Authorization: Bearer <token>' header to the request
- Verify the client library actually sends headers (e.g. set headers in axios defaults/fetch options) and no proxy strips them
- Confirm the request goes through the correct gateway/base URL that expects this auth scheme
- If token extraction should support other header names, update extractToken in middleware.ts
Example fix
// before
await fetch('https://api.example.com/payment/orders')
// after
await fetch('https://api.example.com/payment/orders', {
headers: { Authorization: `Bearer ${accessToken}` }
}) Defensive patterns
Strategy: validation
Validate before calling
const authHeader = headers['authorization'] ?? ''
if (!authHeader.startsWith('Bearer ') || authHeader.length <= 'Bearer '.length) {
throw new Error('Request would fail: no bearer token in Authorization header')
} Type guard
function hasToken(headers: IncomingHttpHeaders): boolean {
const h = headers['authorization']
return typeof h === 'string' && h.startsWith('Bearer ') && h.slice(7).length > 0
} Try / catch
try {
const res = await callApi()
} catch (err) {
if (err.response?.status === 401 && err.response.data?.message === 'Token error') {
// re-authenticate and attach token before retrying
}
} Prevention
- Always attach the Authorization header centrally via an HTTP client interceptor
- Add an integration test asserting every guarded route rejects unauthenticated calls with 401
- Check proxies/gateways do not strip Authorization headers
- Log client-side auth state before requests to catch missing tokens early
When it happens
Trigger: Any request routed through withToken whose headers lack a token — typically a missing or malformed Authorization header (e.g. no 'Authorization: Bearer <token>' header at all, wrong header name, or a client that stripped the header).
Common situations: Forgetting to attach the Authorization header in a frontend fetch/axios call; a proxy or API gateway (e.g. nginx, Kong) dropping the Authorization header; calling the payment pod directly from curl/Postman without auth; OAuth/JWT header casing issues like 'authorization' vs 'Authorization' after custom middleware manipulation.
Related errors
AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29).
Data as JSON: /api/errors/71f14a7e67dc62b2.
Report an issue: GitHub.