How to fix Error: Invalid trailer header (cannot use trailer with chunked encoding) in Node.js

Node.jsINTERMEDIATEMEDIUMUpdated Dec 9, 2025ยท 155 views

This error occurs when Node.js detects conflicting or invalid HTTP trailer headers in a chunked transfer encoding response. Trailers can only be used with chunked encoding, but certain conditions prevent their proper use or declaration.

Quick fix

Fixes ERR_HTTP_INVALID_TRAILER

const http = require('http');

const server = http.createServer((req, res) => {
  // Declare which trailers will be sent after the body
  res.setHeader('Trailer', 'X-Checksum, X-Processing-Time');

  // Enable chunked encoding
  res.setHeader('Transfer-Encoding', 'chunked');
  res.setHeader('Content-Type', 'application/json');

  // Send the body
  res.write(JSON.stringify({ data: 'some data' }));
  res.write(JSON.stringify({ more: 'data' }));

  // Add trailers at the end, before calling end()
  res.addTrailers({
    'X-Checksum': 'abc123def456',
    'X-Processing-Time': '150ms'
  });

  res.end();
});

server.listen(3000);
  1. Declare trailers before sending the response body
  2. Ensure Transfer-Encoding is set to chunked
  3. Use valid header names for trailers
  4. Set trailers only after writing body data
node.js โ€” error
const http = require('http');
const server = http.createServer((req, res) => {
// Declare which trailers will be sent after the body
res.setHeader('Trailer', 'X-Checksum, X-Processing-Time');
// Enable chunked encoding
res.setHeader('Transfer-Encoding', 'chunked');
res.setHeader('Content-Type', 'application/json');
// Send the body
res.write(JSON.stringify({ data: 'some data' }));
res.write(JSON.stringify({ more: 'data' }));
// Add trailers at the end, before calling end()
res.addTrailers({
'X-Checksum': 'abc123def456',
'X-Processing-Time': '150ms'
});
res.end();
});
server.listen(3000);
Error: Invalid trailer header (cannot use trailer with chunked encoding)

What this error means

The ERR_HTTP_INVALID_TRAILER error is raised by Node.js when there is a configuration problem with HTTP trailer headers in relation to chunked transfer encoding. Trailers are HTTP headers that are sent after the message body in chunked encoding, indicated by the Trailer header field which must list all trailer names beforehand. This error typically indicates one of these conditions: (1) attempting to use trailers without chunked encoding enabled, (2) trailer headers that weren't declared in the Trailer header field, (3) invalid trailer header names or values, or (4) improper trailer setup in the response context. HTTP trailers allow servers to send metadata about the response body after transmission (useful for checksums, digital signatures, or post-processing information), but they require specific setup and adherence to HTTP/1.1 specifications.

Typical symptoms

  • HTTP response fails with ERR_HTTP_INVALID_TRAILER when setting trailer headers
  • Error occurs when using res.addTrailers() or similar trailer-setting methods
  • Chunked encoding works fine, but fails as soon as trailers are configured
  • Server crashes or hangs when attempting to send trailer headers
  • Trailer headers are not properly declared before the response body
  • Some trailer header names are rejected as invalid
  • Error occurs intermittently depending on content length or encoding setup

Common causes

  1. Attempting to use trailer headers without Transfer-Encoding: chunked
  2. Trailer header field is not declared before sending the response body
  3. Trailer header names contain invalid characters or reserved names
  4. Trying to modify response headers after body streaming has begun
  5. Improper Content-Length header combined with trailer header usage
  6. Using HTTP/1.0 instead of HTTP/1.1 (trailers only work with HTTP/1.1+)
  7. Trailer header configuration conflicts with compression headers

How to fix "Error: Invalid trailer header (cannot use trailer with chunked encoding)"

1Declare trailers before sending the response body

Use the Trailer header field to declare which trailer headers you intend to send after the response body. This must be set before any body data is written:

javascript
const http = require('http');

const server = http.createServer((req, res) => {
  // Declare which trailers will be sent after the body
  res.setHeader('Trailer', 'X-Checksum, X-Processing-Time');

  // Enable chunked encoding
  res.setHeader('Transfer-Encoding', 'chunked');
  res.setHeader('Content-Type', 'application/json');

  // Send the body
  res.write(JSON.stringify({ data: 'some data' }));
  res.write(JSON.stringify({ more: 'data' }));

  // Add trailers at the end, before calling end()
  res.addTrailers({
    'X-Checksum': 'abc123def456',
    'X-Processing-Time': '150ms'
  });

  res.end();
});

server.listen(3000);

The Trailer header must list all trailer names that will be sent after the body.

2Ensure Transfer-Encoding is set to chunked

Trailers can only be used with chunked transfer encoding. Explicitly set Transfer-Encoding: chunked if you plan to use trailers:

javascript
const http = require('http');

const server = http.createServer((req, res) => {
  // REQUIRED: Set chunked encoding for trailers to work
  res.setHeader('Transfer-Encoding', 'chunked');

  // Declare trailers
  res.setHeader('Trailer', 'X-Signature');

  res.write('First chunk of data\n');
  res.write('Second chunk of data\n');

  // Add trailers before ending
  res.addTrailers({
    'X-Signature': 'signature-value'
  });

  res.end();
});

server.listen(3000);

Do NOT use Content-Length header when using trailers, as it conflicts with chunked encoding.

3Use valid header names for trailers

Trailer header names must be valid HTTP header field names (alphanumeric with hyphens). Some headers like Content-Length, Transfer-Encoding, and Host cannot be trailers:

javascript
const http = require('http');

const server = http.createServer((req, res) => {
  // Valid trailer names (custom or standard metadata headers)
  res.setHeader('Trailer', 'X-File-Checksum, X-Completion-Status');
  res.setHeader('Transfer-Encoding', 'chunked');

  res.write('Data chunk 1\n');
  res.write('Data chunk 2\n');

  // Valid trailers
  res.addTrailers({
    'X-File-Checksum': 'sha256:abc123',
    'X-Completion-Status': 'success'
  });

  res.end();
});

server.listen(3000);

Avoid these forbidden trailer names: Content-Length, Transfer-Encoding, Host, Cache-Control, Expect, Max-Forwards, Pragma, Range, TE, Trailer, Authorization, Proxy-Authorization, etc.

4Set trailers only after writing body data

Trailers must be added using addTrailers() after the body has been written but before calling res.end(). Do not try to set them as response headers:

javascript
const http = require('http');

const server = http.createServer((req, res) => {
  // Set trailers metadata
  res.setHeader('Trailer', 'X-Processing-Time, X-Records-Count');
  res.setHeader('Transfer-Encoding', 'chunked');
  res.setHeader('Content-Type', 'application/json');

  const data = [
    { id: 1, name: 'Record 1' },
    { id: 2, name: 'Record 2' }
  ];

  // Send body
  data.forEach(record => {
    res.write(JSON.stringify(record) + '\n');
  });

  // Add trailers BEFORE res.end()
  res.addTrailers({
    'X-Processing-Time': '42ms',
    'X-Records-Count': data.length.toString()
  });

  res.end();
});

server.listen(3000);

Calling addTrailers() after res.end() will throw an error.

5Verify HTTP version is 1.1 or higher

Trailers are only supported in HTTP/1.1 and HTTP/2. For HTTP/1.0 clients, trailers will be ignored or cause errors:

javascript
const http = require('http');

const server = http.createServer((req, res) => {
  // Check HTTP version
  console.log('HTTP version:', req.httpVersion);

  if (req.httpVersion < '1.1') {
    // HTTP/1.0: Don't use trailers
    res.setHeader('Content-Type', 'application/json');
    res.write(JSON.stringify({ message: 'HTTP/1.0 detected' }));
    res.end();
    return;
  }

  // HTTP/1.1 or higher: Safe to use trailers
  res.setHeader('Trailer', 'X-Version-Info');
  res.setHeader('Transfer-Encoding', 'chunked');

  res.write('Data for HTTP/1.1+');

  res.addTrailers({
    'X-Version-Info': 'HTTP/' + req.httpVersion
  });

  res.end();
});

server.listen(3000);
6Handle trailers on the client side

When consuming responses with trailers, listen for the trailers event to access them:

javascript
const http = require('http');

const options = {
  hostname: 'localhost',
  port: 3000,
  path: '/',
  method: 'GET'
};

const req = http.request(options, (res) => {
  console.log('Status:', res.statusCode);

  res.on('data', (chunk) => {
    console.log('Body chunk:', chunk.toString());
  });

  // Listen for trailers
  res.on('trailers', (trailers) => {
    console.log('Trailers received:', trailers);
    console.log('Checksum:', trailers['x-checksum']);
    console.log('Processing time:', trailers['x-processing-time']);
  });

  res.on('end', () => {
    console.log('Response complete');
  });
});

req.on('error', (e) => {
  console.error('Request error:', e);
});

req.end();

The trailers event is emitted when all trailers have been received, after the body data.

Advanced notes

HTTP/2 Trailers: HTTP/2 has different trailer semantics than HTTP/1.1. In HTTP/2, trailers are sent as header frames after the data frames, and they don't require explicit Transfer-Encoding declaration since HTTP/2 uses frame-based framing. The mechanics are similar but handled differently by the protocol.

Compression and Trailers: When using gzip or deflate compression with trailers, ensure compression is applied only to the body, not the trailers. Some middleware may inadvertently compress trailers or conflict with trailer transmission. Use stream.pipeline() for better composition.

Proxy Compatibility: Many proxies and intermediaries strip or don't support HTTP trailers due to legacy HTTP/1.0 compatibility. In production, trailers may not reach the client if routing through incompatible proxies. Test in your specific network environment.

Performance Considerations: Trailers are useful for checksums (MD5, SHA-256) or digital signatures computed while streaming, avoiding the need to compute them upfront or buffer the entire response. This is more efficient for large responses. However, clients must support and expect trailers, so always document their use.

WebSocket and Upgrades: Trailer headers cannot be used with WebSocket upgrades or other protocol upgrade scenarios. The Upgrade header and trailers conflict, as WebSocket uses a different framing mechanism.

Forbidden Trailer Names: According to RFC 7230, certain header fields are never allowed as trailers: Authorization, Content-Encoding, Content-Length, Content-Range, Host, Pragma, Proxy-Authenticate, Proxy-Authorization, Range, TE, Trailer, Transfer-Encoding, WWW-Authenticate, and Cache-Control.

Debugging Tips: Use curl with verbose mode (curl -v) to see trailers in responses. Add logging at the point where addTrailers() is called to ensure it's executed before res.end(). Check HTTP version in server logs to verify clients support trailers.

Express.js Compatibility: Express doesn't have built-in middleware for trailers. You'll need to work directly with the response object or create custom middleware that properly handles trailer headers and events.

Frequently asked questions

What does "ERR_HTTP_INVALID_TRAILER" mean?
js when there is a configuration problem with HTTP trailer headers in relation to chunked transfer encoding. Trailers are HTTP headers that are sent after the message body in chunked encoding, indicated by the Trailer header field which must list all trailer names beforehand. This error typically indicates one of these conditions: (1) attempting to use trailers without chunked encoding enabled, (2) trailer headers that weren't declared in the Trailer header field, (3) invalid trailer header names or values, or (4) improper trailer setup in the response context.
How do I fix "ERR_HTTP_INVALID_TRAILER"?
This error occurs when Node.js detects conflicting or invalid HTTP trailer headers in a chunked transfer encoding response. Trailers can only be used with chunked encoding, but certain conditions prevent their proper use or declaration.
What causes "ERR_HTTP_INVALID_TRAILER"?
Attempting to use trailer headers without Transfer-Encoding: chunked Trailer header field is not declared before sending the response body Trailer header names contain invalid characters or reserved names
Is the "ERR_HTTP_INVALID_TRAILER" error serious?
It is a medium-severity error โ€” more of a blocker than a risk. The steps above resolve it.

Official resources & further reading