denoland/deno · error · NodeError

ERR_HTTP_BODY_NOT_ALLOWED

ERR_HTTP_BODY_NOT_ALLOWED

Error message

Adding content for this request method or response status is not allowed.

What it means

Some messages must not carry a body: _hasBody is set false for HEAD responses and for 204/304 status codes (see ServerResponse in _http_server.js). If the server was created with rejectNonStandardBodyWrites: true (kRejectNonStandardBodyWrites), write_() throws ERR_HTTP_BODY_NOT_ALLOWED instead of silently dropping the write.

Source

Thrown at ext/node/polyfills/_http_outgoing.ts:1416

      );
    }

    msg[kBytesWritten] += len;
  }

  if (!msg._header) {
    if (fromEnd) {
      len ??= typeof chunk === "string"
        ? Buffer.byteLength(chunk, encoding)
        : TypedArrayPrototypeGetByteLength(chunk);
      msg._contentLength = len;
    }
    msg._implicitHeader();
  }

  if (!msg._hasBody) {
    if (msg[kRejectNonStandardBodyWrites]) {
      throw new ERR_HTTP_BODY_NOT_ALLOWED();
    }
    debug(
      "This type of response MUST NOT have a body. " +
        "Ignoring write() calls.",
    );
    (globalThis as any).process.nextTick(callback);
    return true;
  }

  // Auto-corking
  if (!fromEnd && msg.socket && !msg.socket.writableCorked) {
    msg.socket.cork();
    (globalThis as any).process.nextTick(connectionCorkNT, msg.socket);
  }

  let ret;
  if (msg.chunkedEncoding && chunk.length !== 0) {
    len ??= typeof chunk === "string"

View on GitHub (pinned to 89f33cbef2)

Solutions

  1. Skip the body for bodyless messages: `if (req.method !== 'HEAD' && res.statusCode !== 204 && res.statusCode !== 304)`
  2. End bodyless responses with res.end() (no arguments) - that never throws
  3. If you rely on lenient behavior, do not pass rejectNonStandardBodyWrites: true when creating the server (it defaults to false)

Example fix

// before
const server = http.createServer({ rejectNonStandardBodyWrites: true }, (req, res) => {
  res.writeHead(204);
  res.end('{}'); // throws ERR_HTTP_BODY_NOT_ALLOWED
});

// after
const server = http.createServer({ rejectNonStandardBodyWrites: true }, (req, res) => {
  res.writeHead(204);
  res.end(); // 204 must not have a body
});
Defensive patterns

Strategy: validation

Validate before calling

function canHaveBody(req: http.IncomingMessage, res: http.ServerResponse): boolean {
  return req.method !== 'HEAD' && res.statusCode !== 204 && res.statusCode !== 304;
}
if (canHaveBody(req, res)) res.write(body);
res.end();

Try / catch

try {
  res.write(body);
} catch (e) {
  if (e?.code === 'ERR_HTTP_BODY_NOT_ALLOWED') return; // bodyless message - drop
  throw e;
}

Prevention

When it happens

Trigger: http.createServer({ rejectNonStandardBodyWrites: true }, (req,res) => { res.statusCode = 204; res.end('nope'); }) or writing a body to a response for a HEAD request.

Common situations: Shared handler code that always writes a body but is also routed for HEAD requests and 204/304 'empty' responses (delete/update endpoints); strict-mode servers surfacing previously-silent bugs after enabling the option.

Related errors


AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16). Data as JSON: /api/errors/2635ddc69301f4ac. Report an issue: GitHub.