hcengineering/platform · warning

'to' is missing

Error message

'to' is missing

What it means

handleSendMail returns HTTP 400 { err: "'to' is missing" } when the to field is absent from the request body. The recipient is mandatory; unlike from (which can fall back to config.source), to has no default, so the request is rejected.

Source

Thrown at services/mail/pod-mail/src/main.ts:107

      to
    })
    res.status(401).send({ err: 'Unauthorized' })
    return
  }
  const fromAddress = from ?? config.source
  if (text === undefined && html === undefined) {
    ctx.warn('Text and html are missing in email request', { from, to })
    res.status(400).send({ err: "'text' and 'html' are missing" })
    return
  }
  if (subject === undefined) {
    ctx.warn('Subject is missing in email request', { from, to })
    res.status(400).send({ err: "'subject' is missing" })
    return
  }
  if (to === undefined) {
    ctx.warn('To address is missing in email request', { from })
    res.status(400).send({ err: "'to' is missing" })
    return
  }
  if (fromAddress === undefined) {
    ctx.warn('From address is missing in email request', { to })
    res.status(400).send({ err: "'from' is missing" })
    return
  }
  const message: SendMailOptions = {
    from: fromAddress,
    to,
    subject,
    text
  }
  // When sending system message, ensure we enable replying to a different domain as needed
  if (config.replyTo !== undefined && fromAddress === config.source) {
    message.replyTo = config.replyTo
  }
  if (html !== undefined) {

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Include the to field (recipient address or array) in the request body.
  2. Check for field-name mismatches (recipients/email) between client and pod-mail's expected to.
  3. Validate the payload has to before calling the endpoint (see validationCode in defense section).

Example fix

// before
const body = { from, subject, text } // 400: to missing
// after
const body = { from, to: 'user@example.com', subject, text }
Defensive patterns

Strategy: validation

Validate before calling

function assertRecipient(m: { to?: string | string[] }): void {
  const to = m.to
  const ok = typeof to === 'string' ? to.length > 0 : Array.isArray(to) && to.length > 0
  if (!ok) throw new Error("email requires a 'to' recipient")
}

Type guard

function hasRecipient(m: { to?: unknown }): m is { to: string | string[] } {
  return typeof m.to === 'string' || Array.isArray(m.to)
}

Try / catch

assertRecipient(mail)
const res = await fetch(mailUrl, { method: 'POST', body: JSON.stringify(mail) })
if (res.status === 400) throw new Error(`mail rejected: ${(await res.json()).err}`)

Prevention

When it happens

Trigger: POST to the send-mail endpoint with from/subject/body present but to undefined — e.g. missing recipients array in the payload, a client wrapper dropping the field, or sending recipients in a different field name like recipients or email.

Common situations: Bulk-mail code that forgot to populate the recipient list; renaming to -> recipients in a shared client; serialization stripping undefined fields; sending single-recipient mail with the address in the wrong property.

Related errors


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