Skip to content
Latchkey

SendGrid 400 Bad Request (malformed mail/send) in CI

SendGrid returns HTTP 400 with a specific errors array when the mail/send body is structurally valid JSON but violates the schema, for example a missing content, an empty subject, or a personalizations block with no recipient. The message names the offending field.

What this error means

A SendGrid mail/send call returns HTTP 400 with an errors array pointing at a field like content or personalizations.0.to. No email is sent.

SendGrid API
< HTTP/2 400
{"errors":[{"message":"The content value must be one or more valid content objects.","field":"content","help":null}]}

Common causes

A required field is missing or empty

mail/send requires at least one personalizations recipient, a subject, and a non-empty content array. An empty commit summary can blank the content.

Wrong field types after templating

Building the JSON by string concatenation can put a scalar where an array or object is required.

How to fix it

Build a complete payload with jq

  1. Read the field named in the 400 response.
  2. Ensure content, subject, and a recipient are all present and non-empty.
  3. Construct the JSON with jq so types are correct.
Terminal
body="${SUMMARY:-CI run completed}"
jq -n --arg b "$body" '{
  personalizations:[{to:[{email:"team@example.com"}]}],
  from:{email:"ci@your-verified-domain.com"},
  subject:"CI result",
  content:[{type:"text/plain",value:$b}]}' > mail.json

Default empty values

Guard against an empty subject or body so the schema is always satisfied.

Terminal
[ -n "$SUMMARY" ] || SUMMARY="CI run completed"

How to prevent it

  • Validate the mail/send JSON shape before sending.
  • Default the subject and body so required fields are never empty.
  • Build payloads with jq rather than string concatenation.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →