Skip to content
Latchkey

Cloudflare purge cache 400 "Invalid request headers" in CI

Cloudflare rejected the request before checking the token: a 400 with code 6003 "Invalid request headers" means a header is malformed, most often mixing bearer-token and legacy X-Auth-Key auth, or sending an empty Authorization value.

What this error means

The purge call returns HTTP 400 with error code 6003 and sub-errors like 6111 "Invalid format for Authorization header". It fails identically on every run.

Cloudflare API
{
  "success": false,
  "errors": [
    { "code": 6003, "message": "Invalid request headers",
      "error_chain": [
        { "code": 6111, "message": "Invalid format for Authorization header" }
      ] }
  ]
}

Common causes

Bearer and legacy auth headers are mixed

The request sends both Authorization: Bearer and X-Auth-Key/X-Auth-Email, or a bearer token with the legacy X-Auth-* headers, which Cloudflare rejects as invalid.

The Authorization header is empty or malformed

An unset secret expands to Authorization: Bearer with no value, so the header format is invalid and never reaches token verification.

How to fix it

Use exactly one auth scheme

  1. For an API token, send only Authorization: Bearer <token>.
  2. For the legacy key, send only X-Auth-Email and X-Auth-Key; do not combine the two.
  3. Confirm the secret is non-empty so the header has a value.
Terminal
# API token (preferred): one header only
curl -sS -X POST \
  "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/purge_cache" \
  -H "Authorization: Bearer ${CF_API_TOKEN}" \
  -H "Content-Type: application/json" \
  --data '{"purge_everything":true}'

Guard against an empty token

Fail fast if the secret did not populate so the header is never sent empty.

Terminal
if [ -z "${CF_API_TOKEN}" ]; then
  echo "CF_API_TOKEN is empty; check the secret binding"; exit 1
fi

How to prevent it

  • Pick one auth scheme (bearer token) and remove legacy X-Auth headers.
  • Assert the token secret is non-empty before building the header.
  • Always set Content-Type: application/json on the purge request.

Related guides

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