{"record":{"id":"e68b8af22640423e","repo":"hcengineering/platform","slug":"err-code-e68b8a","errorCode":"err.code","errorMessage":"err.message","messagePattern":"err\\.message","errorType":"http","errorClass":"ApiError","httpStatus":400,"severity":"error","filePath":"services/mail/pod-mail/src/server.ts","lineNumber":53,"sourceCode":"\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): Server {\n  const cb = (): void => {\n    console.log(`Mail service has been started at ${host ?? '*'}:${port}`)\n  }\n\n  return host !== undefined ? e.listen(port, host, cb) : e.listen(port, cb)\n}\n","sourceCodeStart":35,"sourceCodeEnd":70,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/services/mail/pod-mail/src/server.ts#L35-L70","documentation":"The pod-mail error-handling middleware catches an ApiError thrown (or forwarded via catchError) by an endpoint handler and responds HTTP 400 with { code: err.code, message: err.message }. The message text is whatever the ApiError carried — often a field-validation message like \"'from' is missing\". It signals a client-side bad request rather than a server fault.","triggerScenarios":"Any endpoint handler throws ApiError (directly or via the catchError wrapper) with a 4xx-class code — e.g. malformed request parameters, invalid token format, or payload that fails domain validation inside pod-mail.","commonSituations":"Client sending payloads that pass the top-level undefined checks but fail deeper validation inside the mail handler; code reusing ApiError from the shared server library for business-rule violations; SDK wrappers surfacing the raw { code, message } body to application code.","solutions":["Read the 'code' and 'message' fields in the 400 response body — they identify exactly which validation failed; fix the request payload accordingly.","In client code, parse the response body and branch on code instead of treating every non-2xx as a generic failure.","If the ApiError originates from your own handler code, correct the thrown condition or throw a more specific ApiError code.","Ensure catchError wraps handlers so ApiErrors surface as 400 rather than becoming 500s."],"exampleFix":"// before\nconst res = await fetch(url, opts)\nconst data = await res.json()\nuse(data)\n// after\nif (!res.ok) {\n  const err = await res.json()\n  if (err.code) throw new Error(`ApiError ${err.code}: ${err.message}`)\n}\nconst data = await res.json()\nuse(data)","handlingStrategy":"try-catch","validationCode":"function isApiErrorBody(b: unknown): b is { code: string; message: string } {\n  return typeof (b as any)?.code === 'string' && typeof (b as any)?.message === 'string'\n}","typeGuard":"function isApiErrorBody(v: unknown): v is { code: string; message: string } {\n  return v !== null && typeof v === 'object' && 'code' in v && 'message' in v\n}","tryCatchPattern":"const res = await fetch(url, opts)\nif (!res.ok) {\n  const body = await res.json()\n  if (isApiErrorBody(body)) throw new Error(`ApiError ${body.code}: ${body.message}`)\n  throw new Error(`HTTP ${res.status}`)\n}","preventionTips":["Always branch on the response 'code' field instead of the status alone","Validate the full request payload against the endpoint's schema before sending","Log code+message together to make failures greppable"],"tags":["http-400","api-error","validation","express"],"backgroundTag":"api-error-400","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}