{"record":{"id":"b4f73755e4d876bc","repo":"hcengineering/platform","slug":"not-found-b4f737","errorCode":null,"errorMessage":"Not found","messagePattern":"Not found","errorType":"http","errorClass":null,"httpStatus":404,"severity":"warning","filePath":"services/notification/pod-notification/src/server.ts","lineNumber":47,"sourceCode":"  })()\n}\n\nexport function createServer (endpoints: Endpoint[]): Express {\n  const app = express()\n\n  app.use(cors())\n  app.use(express.json())\n\n  endpoints.forEach((endpoint) => {\n    if (endpoint.type === 'get') {\n      app.get(endpoint.endpoint, catchError(endpoint.handler))\n    } else if (endpoint.type === 'post') {\n      app.post(endpoint.endpoint, catchError(endpoint.handler))\n    }\n  })\n\n  app.use((_req, res, _next) => {\n    res.status(404).send({ message: 'Not found' })\n  })\n\n  app.use((err: any, _req: any, res: any, _next: any) => {\n    if (err instanceof ApiError) {\n      res.status(400).send({ code: err.code, message: err.message })\n      return\n    }\n\n    res.status(500).send({ message: err.message })\n  })\n\n  return app\n}\n\nexport function listen (e: Express, port: number, host?: string, onListening?: () => void): Server {\n  const cb = (): void => {\n    if (onListening !== undefined) {\n      onListening()","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/services/notification/pod-notification/src/server.ts#L29-L65","documentation":"The pod-notification Express server registers a catch-all middleware that replies HTTP 404 { message: 'Not found' } when no registered endpoint matched the request. It is the route-matching fallback, not a handler error. The notification pod registers its endpoints via createServer; anything else — wrong path or wrong HTTP verb — lands here.","triggerScenarios":"Requesting a path not among the registered notification endpoints, using GET where type is 'post', or hitting the notification pod expecting mail-pod routes (the two services share the same 404 body).","commonSituations":"Service discovery misconfiguration pointing clients at the wrong pod; path prefix changes after gateway updates; forgetting that push endpoints require POST; probing the service for documentation endpoints that do not exist.","solutions":["Compare the request method+path against the endpoints registered in pod-notification's main.ts and correct the URL/verb.","Verify the target host:port is the notification pod, not the mail pod (identical 404 bodies make this easy to confuse).","Check gateway/ingress path rewrites that might alter the prefix before it reaches Express.","Temporarily log req.method and req.originalUrl before the 404 middleware to see the exact incoming route."],"exampleFix":"// before\nawait fetch('http://notify:3040/push', { method: 'GET' })\n// after\nawait fetch('http://notify:3040/push', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body })","handlingStrategy":"validation","validationCode":"const NOTIFY_ROUTES = ['/push'] // paths registered by pod-notification\nfunction assertNotifyRoute(method: string, path: string) {\n  if (method !== 'POST' || !NOTIFY_ROUTES.includes(path)) throw new Error(`unknown notification route ${method} ${path}`)\n}","typeGuard":null,"tryCatchPattern":"const res = await fetch(url, opts)\nif (res.status === 404) throw new Error(`notification pod has no route for ${opts.method} ${url} — verify path, verb, and target pod`)","preventionTips":["Share route constants between client and server endpoint registration","Distinguish notification pod from mail pod ports in config to avoid cross-pod 404s","Use POST for push endpoints; do not probe undocumented paths"],"tags":["http-404","routing","express","rest"],"backgroundTag":"http-404-not-found","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}