hcengineering/platform · warning
'data' is missing
Error message
'data' is missing
What it means
The /push endpoint receives Google Pub/Sub push notifications for Gmail events. The Pub/Sub envelope wraps the payload in body.message.data (base64). If that field is absent, the endpoint rejects the request with 400 and this fixed message — it is a payload-shape validation, not an exception.
Source
Thrown at services/gmail/pod-gmail/src/main.ts:161
const { account, workspace } = decodeToken(token)
await gmailController.signout(workspace, account)
} catch (err) {
ctx.error('signout error', { message: JSON.stringify(err) })
}
res.send()
}
},
{
endpoint: '/push',
type: 'post',
handler: async (req, res) => {
try {
const data = req.body?.message?.data
if (data === undefined) {
res.status(400).send({ err: "'data' is missing" })
return
}
gmailController.push(data)
res.send()
} catch (err: any) {
ctx.error('Push request failed', { message: err.message })
res.status(500).send()
}
}
},
{
endpoint: '/state',
type: 'get',
handler: async (req, res) => {
try {
const token = extractToken(req.headers)
View on GitHub (pinned to 63e28dc964)
Solutions
- Send the full Google Pub/Sub push envelope: { "message": { "data": "<base64>", ... } }.
- Base64-encode the Gmail notification payload before publishing to the topic.
- Verify the Pub/Sub subscription is a push subscription with the default JSON envelope format.
Example fix
// before
{ "data": "<base64>" }
// after
{ "message": { "data": "<base64>", "messageId": "...", "publishTime": "..." } } Defensive patterns
Strategy: validation
Validate before calling
function isPubsubPushEnvelope(body: any): body is { message: { data: string } } {
return body != null && typeof body === 'object' &&
body.message != null && typeof body.message.data === 'string' && body.message.data.length > 0
}
// reject early: if (!isPubsubPushEnvelope(req.body)) return res.status(400)… Type guard
function isPubsubPushEnvelope(v: unknown): v is { message: { data: string } } {
return typeof v === 'object' && v !== null &&
'message' in v && typeof (v as any).message?.data === 'string'
} Try / catch
try {
const res = await fetch(pushUrl, { method: 'POST', body: JSON.stringify(envelope) })
if (res.status === 400) {
const body = await res.json()
if (body?.err === "'data' is missing") {
// wrap payload in the Pub/Sub push envelope and retry
}
}
} catch (e) { /* network error handling */ } Prevention
- Always publish to the topic the full Pub/Sub message; let Pub/Sub build the push envelope.
- Use a Pub/Sub push subscription (default JSON wrapper) rather than posting raw payloads.
- When testing manually, replicate the full envelope including base64-encoded data.
- Base64-encode the inner Gmail payload before publishing.
When it happens
Trigger: POST to /push whose JSON body lacks body.message.data — e.g. a plain-text ping, a Pub/Sub 'pull'-style message posted incorrectly, or a non-Pub/Sub client calling the endpoint.
Common situations: Manually testing the endpoint with curl/Postman and sending the inner payload directly instead of the Pub/Sub push envelope; configuring a Pub/Sub subscription with the wrong push format (non-JSON wrapper); a load balancer rewriting the body.
Related errors
- Failed to load server config
- getDisplayMedia not supported
- No screen access granted
- platform.status.BadRequest
- Invalid format. Supported formats: ${supportedExportFormats.
AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29).
Data as JSON: /api/errors/022dd1758a6bd4bb.
Report an issue: GitHub.