hcengineering/platform · error
err.message
Error message
err.message
What it means
The pod-mail-worker's Express error middleware returns 500 with { message: err.message } for any unhandled route error. For /mta-hook specifically it instead responds 200 { action: 'accept' } so the upstream mail server keeps accepting emails. Seeing this 500 means an error escaped a non-mta-hook route (or an error middleware path other than the mta-hook branch).
Source
Thrown at services/mail/pod-mail-worker/src/index.ts:87
}
})()
}
app.post('/mta-hook', catchError(handleMtaHook))
app.use((_req, res, _next) => {
res.status(404).send({ message: 'Not found' })
})
app.use((err: any, req: Request, res: any, _next: any) => {
ctx.error(err)
if (req.path === '/mta-hook') {
// Any error in the mta-hook should not prevent the mail server from handling emails
// At least the PayloadTooLargeError falls here before reacing our code
res.status(200).send({ action: 'accept' })
return
}
res.status(500).send({ message: err.message })
})
const server = app.listen(config.port, () => {
ctx.info('server started', {
...config,
secret: config.secret !== undefined ? '(stripped)' : undefined,
hookToken: config.hookToken !== undefined ? '(stripped)' : undefined,
storageConfig: config.storageConfig !== undefined ? '(stripped)' : undefined
})
})
await MailWorker.create(ctx)
const shutdown = (): void => {
try {
MailWorker.getMailWorker()
.close()
.catch((err) => {
ctx.error('Failed to close MailWorker', { error: err.message })View on GitHub (pinned to 63e28dc964)
Solutions
- Read the returned err.message (and worker logs via ctx.error) to identify the underlying failure.
- If it is PayloadTooLargeError, reduce the payload size or raise the body-parser limit configured in the worker.
- If it is a JSON parse error, send valid JSON with Content-Type: application/json.
- Fix or wrap the failing route handler with catchError so errors are handled where they occur.
Example fix
// before
app.post('/hook', async (req, res) => { throw new Error('boom') }) // becomes 500 err.message
// after
app.post('/hook', catchError(async (req, res) => { ... })) Defensive patterns
Strategy: try-catch
Validate before calling
// Guard payload size and JSON validity before sending
const serialized = JSON.stringify(payload)
if (serialized.length > MAX_BODY_BYTES) throw new Error('payload exceeds body-parser limit')
JSON.parse(serialized) // throws early on non-serializable/corrupt payload Type guard
function isSerializableJson(v: unknown): boolean {
try { JSON.stringify(v); return true } catch { return false }
} Try / catch
try {
const res = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) })
if (!res.ok) {
const { message } = await res.json()
throw new Error(`worker 500: ${message}`)
}
} catch (e) {
ctx.error('mail worker request failed', { e })
} Prevention
- Keep request bodies under the configured body-parser limit.
- Always send valid JSON with the correct Content-Type.
- Wrap new route handlers in catchError so errors don't hit the generic 500 middleware.
- Check worker logs (ctx.error) for the full stack behind the returned err.message.
When it happens
Trigger: An uncaught exception thrown synchronously or via next(err) in a pod-mail-worker route — e.g. body-parser PayloadTooLargeError on a non-mta-hook route, JSON parse failure, or a handler crash reaching the error middleware outside the req.path === '/mta-hook' branch.
Common situations: Sending an oversized payload that exceeds the body-parser limit; sending malformed JSON that the body parser rejects; a bug in a newly added worker route; proxies forwarding requests with unexpected content types.
Related errors
AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29).
Data as JSON: /api/errors/0b5f889253e73c4c.
Report an issue: GitHub.