{"record":{"id":"a327fa2701d2e93a","repo":"hcengineering/platform","slug":"data-is-missing-a327fa","errorCode":null,"errorMessage":"'data' is missing","messagePattern":"'data' is missing","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"services/notification/pod-notification/src/main.ts","lineNumber":69,"sourceCode":"      if (token !== config.AuthToken) {\n        res.status(401).send({ err: 'Invalid auth token' })\n        return false\n      }\n    }\n    return true\n  }\n\n  const endpoints: Endpoint[] = [\n    {\n      endpoint: '/web-push',\n      type: 'post',\n      handler: async (req, res) => {\n        if (!checkAuth(req, res)) {\n          return\n        }\n        const data: PushData | undefined = req.body?.data\n        if (data === undefined) {\n          res.status(400).send({ err: \"'data' is missing\" })\n          return\n        }\n        const subscriptions: PushSubscription[] | undefined = req.body?.subscriptions\n        if (subscriptions === undefined) {\n          res.status(400).send({ err: \"'subscriptions' is missing\" })\n          return\n        }\n        if (!webpushInitDone) {\n          res.json({ result: [] }).end()\n          return\n        }\n\n        const result = await sendPushToSubscription(ctx, subscriptions, data)\n        res.json({ result }).end()\n      }\n    }\n  ]\n","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/services/notification/pod-notification/src/main.ts#L51-L87","documentation":"The pod-notification push handler responds HTTP 400 with { err: \"'data' is missing\" } when req.body.data is undefined. The handler builds a PushData from body.data and needs it to compose the web-push notification payload, so it rejects the request before looking at subscriptions.","triggerScenarios":"POST to the push endpoint (passing checkAuth) with a body lacking the 'data' object, a non-JSON body, or data nested one level too deep (e.g. { payload: { data } } instead of { data }).","commonSituations":"Wrong Content-Type so express.json() never populates req.body; renaming the field in the client ('notification', 'payload', 'message') while the service expects 'data'; older clients built for a schema where data was optional; gateway stripping the body on forwarded POSTs.","solutions":["Include a valid 'data' object in the JSON body: {\"data\":{...},\"subscriptions\":[...]}.","Set Content-Type: application/json and confirm the body is not empty after proxies/gateways.","Match the PushData shape expected by the service (check its type definition) rather than sending arbitrary fields.","Validate the payload client-side before sending (see type guard) to fail fast with a clearer message."],"exampleFix":"// before\npost(pushUrl, { subscriptions })\n// after\npost(pushUrl, { data: { title: 'Hi', body: 'Hello' }, subscriptions })","handlingStrategy":"validation","validationCode":"function hasPushData(body: unknown): boolean {\n  const d = (body as any)?.data\n  return d !== undefined && d !== null && typeof d === 'object'\n}\nif (!hasPushData(payload)) throw new Error(\"push request requires a 'data' object\")","typeGuard":"function hasPushData(b: unknown): b is { data: object; subscriptions: unknown[] } {\n  const d = (b as any)?.data\n  return typeof d === 'object' && d !== null\n}","tryCatchPattern":"const res = await fetch(pushUrl, opts)\nif (res.status === 400) {\n  const { err } = await res.json()\n  if (err?.includes(\"'data' is missing\")) throw new Error('push payload must include data')\n}","preventionTips":["Build push requests through one typed helper so data is always present","Send Content-Type: application/json explicitly","Keep the field named exactly 'data' — no client-side renames"],"tags":["http-400","validation","web-push","missing-field"],"backgroundTag":"missing-request-field","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}