hcengineering/platform · warning

Not found

Error message

Not found

What it means

The pod-mail Express server has a catch-all middleware that responds 404 { message: 'Not found' } to any request that did not match a registered endpoint. It is not thrown by handler code — it is the terminal route-matching fallback. It means the URL path or HTTP method did not correspond to any endpoint registered via createServer.

Source

Thrown at services/mail/pod-mail/src/server.ts:48

  })()
}

export function createServer (endpoints: Endpoint[]): Express {
  const app = express()

  app.use(cors())
  app.use(express.json())

  endpoints.forEach((endpoint) => {
    if (endpoint.type === 'get') {
      app.get(endpoint.endpoint, catchError(endpoint.handler))
    } else if (endpoint.type === 'post') {
      app.post(endpoint.endpoint, catchError(endpoint.handler))
    }
  })

  app.use((_req, res, _next) => {
    res.status(404).send({ message: 'Not found' })
  })

  app.use((err: any, _req: any, res: any, _next: any) => {
    if (err instanceof ApiError) {
      res.status(400).send({ code: err.code, message: err.message })
      return
    }

    res.status(500).send({ message: err.message })
  })

  return app
}

export function listen (e: Express, port: number, host?: string): Server {
  const cb = (): void => {
    console.log(`Mail service has been started at ${host ?? '*'}:${port}`)
  }

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Check the request URL against the endpoint paths registered in pod-mail's main.ts and correct the path or HTTP method.
  2. Confirm the client is hitting the mail pod's host:port, not another pod (pod-mail and pod-notification have identical 404 bodies).
  3. Inspect any reverse-proxy/gateway rewrite rules that may strip or prepend path prefixes.
  4. Log the full incoming req.method + req.originalUrl (temporarily add middleware before the 404 handler) to see what actually reaches the server.

Example fix

// before
await fetch('http://mail:3040/send-mail', ...)
// after (path matching the registered post endpoint)
await fetch('http://mail:3040/sendmail', { method: 'POST', ... })
Defensive patterns

Strategy: validation

Validate before calling

const MAIL_ROUTES = ['/sendmail'] // paths registered by pod-mail
function assertMailRoute(method: string, path: string) {
  if (method !== 'POST' || !MAIL_ROUTES.includes(path)) throw new Error(`unknown mail route ${method} ${path}`)
}

Try / catch

const res = await fetch(url, opts)
if (res.status === 404) throw new Error(`mail pod has no route for ${opts.method} ${url} — check path/method and target port`)

Prevention

When it happens

Trigger: GET/POST to a path not in the endpoint table (e.g. wrong service prefix, wrong port routing to the wrong pod, trailing path segments), or using GET on an endpoint registered with type 'post'.

Common situations: Proxy or gateway rewriting paths and dropping/adding prefixes; calling the mail pod on the notification pod's port (or vice versa — both return the identical 404 body); API version path changed after upgrade; typo in endpoint path like /sendmail vs /send-mail.

Related errors


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