Introduction
Axios in Node.js can fail in a confusing way when the request body is a stream, form-data instance, or another object that Axios expects to measure before sending. A common failure path is around data.getLength(...) in the Node HTTP adapter. Instead of a clean application error, the request may hang, abort, or surface an unhelpful stack trace depending on the Axios version and the payload helper you used.
Symptoms
- Requests fail only in Node.js, not in the browser
- Multipart uploads hang or terminate before the request is fully sent
- Stack traces mention
getLength,form-data, or the Axios HTTP adapter - The issue appears after switching payload libraries or upgrading Axios
Common Causes
- A payload object is not a real
form-datainstance even though Axios treats it like one form-datacannot calculate content length for one of the appended values- Headers from
form.getHeaders()were not merged into the Axios request - A custom stream or buffer wrapper does not expose the shape Axios expects
Step-by-Step Fix
- 1.Confirm the payload type before Axios sends it
- 2.Check whether the request body is actually a
form-dataobject with the methods Axios expects.
```javascript import FormData from "form-data";
const form = new FormData(); form.append("file", fs.createReadStream("./upload.bin"));
console.log(form instanceof FormData); console.log(typeof form.getLength, typeof form.getHeaders); ```
- 1.Calculate content length explicitly
- 2.If length resolution is the failing step, call it yourself so you can see the real error instead of a vague adapter failure.
```javascript form.getLength((error, length) => { if (error) { console.error("getLength failed", error); return; }
console.log("content-length", length); }); ```
- 1.Pass multipart headers and avoid mixed payload helpers
- 2.Do not combine browser
FormDataassumptions with Nodeform-databehavior.
```javascript const headers = form.getHeaders();
const response = await axios.post("https://api.example.com/upload", form, { headers, maxBodyLength: Infinity, }); ```
- 1.Fall back to a buffered upload when length detection is unreliable
- 2.For some integrations, using a buffer with explicit headers is simpler and more stable than dynamic length detection.
```javascript const body = fs.readFileSync("./upload.bin");
await axios.post("https://api.example.com/upload", body, { headers: { "content-type": "application/octet-stream", "content-length": body.length, }, }); ```
Prevention
- Use one multipart library consistently in Node.js code paths
- Log payload type and headers before investigating Axios adapter internals
- Test uploads with the exact runtime version of Axios used in production
- Prefer explicit content length when the upstream requires strict request framing