{"record":{"id":"744304aa481a09dc","repo":"denoland/deno","slug":"err-http-trailer-invalid","errorCode":"ERR_HTTP_TRAILER_INVALID","errorMessage":"Trailers are invalid with this transfer encoding","messagePattern":"Trailers are invalid with this transfer encoding","errorType":"error_code","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/_http_outgoing.ts","lineNumber":1061,"sourceCode":"          this.chunkedEncoding = true;\n        } else {\n          // We should only be able to get here if both Content-Length and\n          // Transfer-Encoding are removed by the user.\n          // See: test/parallel/test-http-remove-header-stays-removed.js\n          debug(\"Both Content-Length and Transfer-Encoding are removed\");\n\n          // We can't keep alive in this case, because with no header info the body\n          // is defined as all data until the connection is closed.\n          this._last = true;\n        }\n      }\n\n      // Test non-chunked message does not have trailer header set,\n      // message will be terminated by the first empty line after the\n      // header fields, regardless of the header fields present in the\n      // message, and thus cannot contain a message body or 'trailers'.\n      if (this.chunkedEncoding !== true && state.trailer) {\n        throw new ERR_HTTP_TRAILER_INVALID();\n      }\n\n      const { header } = state;\n      this._header = header + \"\\r\\n\";\n\n      // Wait until the first body chunk, or close(), is sent to flush,\n      // UNLESS we're sending Expect: 100-continue.\n      if (state.expect) this._send(\"\");\n    },\n    writable: true,\n    enumerable: true,\n    configurable: true,\n  },\n  _storeHeaderEntry: {\n    __proto__: null,\n    value: function _storeHeaderEntry(\n      state: any,\n      field: string,","sourceCodeStart":1043,"sourceCodeEnd":1079,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/node/polyfills/_http_outgoing.ts#L1043-L1079","documentation":"OutgoingMessage._storeHeader rejects a message that declares a Trailer header while its transfer encoding is not chunked (this.chunkedEncoding !== true). HTTP trailers are only defined for chunked bodies - a non-chunked message ends at the first empty line after headers, so a trailer could never be delivered - hence ERR_HTTP_TRAILER_INVALID at header-assembly time.","triggerScenarios":"res.setHeader('Trailer', 'X-Foo') combined with anything that disables chunking: an explicit content-length header, HTTP/1.0 client (server forces _last and no chunked), or writeHead with content-length. Also adding 'Trailer' to an array/object headers argument on a non-chunked request.","commonSituations":"Adding trailing metadata (checksums, timing headers) without realizing the response got a fixed content-length (e.g. serving a file with known size); proxying HTTP/1.0 clients; frameworks that auto-set content-length for small bodies, silently disabling chunked encoding.","solutions":["Remove the explicit content-length header so an HTTP/1.1 response can use chunked encoding with trailers.","Drop the Trailer header and send the metadata as a normal header or in the body when you must keep content-length.","Ensure the client connection is HTTP/1.1 (chunked is not negotiated for 1.0 responses)."],"exampleFix":"// before\nres.setHeader('Trailer', 'X-Checksum');\nres.setHeader('content-length', body.length); // chunking off -> throws\nres.end(body);\n\n// after\nres.setHeader('Trailer', 'X-Checksum');\nres.removeHeader('content-length'); // chunked encoding -> trailers legal\nres.write(body);\nres.addTrailers({ 'X-Checksum': sum });\nres.end();","handlingStrategy":"validation","validationCode":"// trailers are only legal with chunked encoding: no content-length and HTTP/1.1\nconst canTrailer = res.req?.httpVersionMajor === 1 &&\n  res.req?.httpVersionMinor >= 1 &&\n  !res.hasHeader('content-length');\nif (canTrailer) res.setHeader('Trailer', 'X-Checksum');","typeGuard":null,"tryCatchPattern":"try {\n  res.setHeader('Trailer', 'X-Foo');\n  res.writeHead(200);\n} catch (err) {\n  if (err.code === 'ERR_HTTP_TRAILER_INVALID') {\n    res.removeHeader('Trailer');\n    res.writeHead(200); // retry without trailers\n  } else throw err;\n}","preventionTips":["Never combine a Trailer header with an explicit content-length.","Confirm the client is HTTP/1.1 before advertising trailers.","Send trailing metadata in the body when a fixed content-length is required."],"tags":["http","node-compat","trailers","chunked-encoding"],"backgroundTag":"invalid-http-trailer","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}