How to fix Error: HPE_UNEXPECTED_EOF (unexpected end of HTTP) in Node.js

Node.jsINTERMEDIATEMEDIUMUpdated Dec 9, 2025· 192 views

The HPE_UNEXPECTED_EOF error occurs when Node.js HTTP parser encounters an unexpected end-of-file during HTTP response parsing. This typically happens when the server closes the connection prematurely before sending the complete HTTP response, leaving the client with incomplete data.

Quick fix

Fixes HPE_UNEXPECTED_EOF

const http = require('http');

function makeRequestWithRetry(options, maxRetries = 3) {
  return new Promise((resolve, reject) => {
    let attempt = 0;

    function attemptRequest() {
      attempt++;

      const req = http.request(options, (res) => {
        let data = '';

        res.on('data', (chunk) => {
          data += chunk;
        });

        res.on('end', () => {
          resolve(data);
        });

        res.on('error', handleError);
      });

      req.on('error', handleError);

      function handleError(err) {
        if (err.code === 'HPE_UNEXPECTED_EOF' && attempt < maxRetries) {
          const delay = Math.pow(2, attempt) * 100; // Exponential backoff
          console.log(`Retry attempt ${attempt} after ${delay}ms`);
          setTimeout(attemptRequest, delay);
        } else {
          reject(err);
        }
      }

      req.end();
    }

    attemptRequest();
  });
}
  1. Add error handling and retry logic to your HTTP requests
  2. Configure appropriate timeout values for requests
  3. Use HTTP client libraries with better error handling
  4. Verify server-side response handling
node.js — error
const http = require('http');
function makeRequestWithRetry(options, maxRetries = 3) {
return new Promise((resolve, reject) => {
let attempt = 0;
function attemptRequest() {
attempt++;
const req = http.request(options, (res) => {
let data = '';
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
resolve(data);
});
res.on('error', handleError);
});
req.on('error', handleError);
function handleError(err) {
if (err.code === 'HPE_UNEXPECTED_EOF' && attempt < maxRetries) {
const delay = Math.pow(2, attempt) * 100; // Exponential backoff
console.log(`Retry attempt ${attempt} after ${delay}ms`);
setTimeout(attemptRequest, delay);
} else {
reject(err);
}
}
req.end();
}
attemptRequest();
});
}
Error: HPE_UNEXPECTED_EOF (unexpected end of HTTP)

What this error means

The HPE_UNEXPECTED_EOF (HTTP Parser Error - Unexpected End Of File) is thrown by Node.js's internal HTTP parser (llhttp) when it encounters an unexpected termination of the HTTP response stream. This error specifically indicates that the connection was closed by the server or network before the HTTP parser could finish reading the complete response based on the Content-Length header or chunked transfer encoding expectations. When an HTTP response is being received, the parser expects certain data patterns—either a specific number of bytes indicated by the Content-Length header, or properly terminated chunked encoding with a final zero-length chunk. If the socket closes before this expected data is fully received, the parser raises HPE_UNEXPECTED_EOF to signal that the response is incomplete. This is distinct from other HTTP parser errors like HPE_INVALID_CONSTANT or HPE_HEADER_OVERFLOW, as it specifically relates to premature connection termination rather than malformed HTTP data or protocol violations.

Typical symptoms

  • HTTP requests fail with "Error: HPE_UNEXPECTED_EOF" in Node.js applications
  • API calls or web scraping operations intermittently throw parser errors
  • Error occurs during response body parsing, not during connection establishment
  • Proxied HTTP requests fail with unexpected EOF errors
  • Connection works in browsers or other HTTP clients but fails in Node.js
  • Error is more frequent with slow or unreliable network connections
  • Logs show socket closed unexpectedly before response completion

Common causes

  1. Server closes the connection before sending the complete response body indicated by Content-Length
  2. Network instability or packet loss causes the TCP connection to drop during transmission
  3. Server timeout occurs while generating the response, closing the connection mid-stream
  4. Keep-alive timeout mismatch between client and server (server closes reused connection)
  5. Reverse proxy or load balancer terminates connection prematurely due to its own timeout
  6. Server crashes or restarts while handling the request
  7. Firewall or NAT device drops the connection after idle time
  8. Content-Length header incorrectly specifies more bytes than the server actually sends
  9. Chunked transfer encoding stream is not properly terminated with zero-length chunk

How to fix "Error: HPE_UNEXPECTED_EOF (unexpected end of HTTP)"

1Add error handling and retry logic to your HTTP requests

Implement proper error handling with exponential backoff to gracefully handle transient connection issues:

javascript
const http = require('http');

function makeRequestWithRetry(options, maxRetries = 3) {
  return new Promise((resolve, reject) => {
    let attempt = 0;

    function attemptRequest() {
      attempt++;

      const req = http.request(options, (res) => {
        let data = '';

        res.on('data', (chunk) => {
          data += chunk;
        });

        res.on('end', () => {
          resolve(data);
        });

        res.on('error', handleError);
      });

      req.on('error', handleError);

      function handleError(err) {
        if (err.code === 'HPE_UNEXPECTED_EOF' && attempt < maxRetries) {
          const delay = Math.pow(2, attempt) * 100; // Exponential backoff
          console.log(`Retry attempt ${attempt} after ${delay}ms`);
          setTimeout(attemptRequest, delay);
        } else {
          reject(err);
        }
      }

      req.end();
    }

    attemptRequest();
  });
}

This adds resilience against temporary connection issues.

2Configure appropriate timeout values for requests

Set explicit timeout values to prevent indefinite hangs and ensure connections are properly managed:

javascript
const http = require('http');

const options = {
  hostname: 'example.com',
  path: '/api/data',
  method: 'GET',
  timeout: 30000, // 30 second timeout
  // Ensure server keep-alive is longer than client timeout
  headers: {
    'Connection': 'keep-alive',
    'Keep-Alive': 'timeout=5, max=100'
  }
};

const req = http.request(options, (res) => {
  // Handle response
});

// Handle timeout specifically
req.on('timeout', () => {
  console.error('Request timed out');
  req.destroy(); // Destroy the request
});

req.on('error', (err) => {
  if (err.code === 'HPE_UNEXPECTED_EOF') {
    console.error('Server closed connection prematurely');
  }
});

req.end();

For servers, ensure your keep-alive timeout is longer than client expectations:

javascript
const server = http.createServer((req, res) => {
  // Handle requests
});

// Set server keep-alive timeout to 65 seconds
// (longer than typical client 60s timeout)
server.keepAliveTimeout = 65000;
server.headersTimeout = 66000; // Slightly longer than keepAliveTimeout

server.listen(3000);
3Use HTTP client libraries with better error handling

Consider using more robust HTTP client libraries that handle connection issues more gracefully:

javascript
// Using axios with retry logic
const axios = require('axios');
const axiosRetry = require('axios-retry');

const client = axios.create({
  timeout: 30000,
  httpAgent: new http.Agent({
    keepAlive: true,
    keepAliveMsecs: 30000
  })
});

// Configure automatic retries
axiosRetry(client, {
  retries: 3,
  retryDelay: axiosRetry.exponentialDelay,
  retryCondition: (error) => {
    return axiosRetry.isNetworkOrIdempotentRequestError(error) ||
           error.code === 'HPE_UNEXPECTED_EOF';
  }
});

// Make request
try {
  const response = await client.get('https://api.example.com/data');
  console.log(response.data);
} catch (error) {
  console.error('Request failed after retries:', error.message);
}

Or using got with built-in retry:

javascript
const got = require('got');

try {
  const response = await got('https://api.example.com/data', {
    timeout: {
      request: 30000
    },
    retry: {
      limit: 3,
      methods: ['GET', 'POST'],
      statusCodes: [408, 413, 429, 500, 502, 503, 504],
      errorCodes: [
        'ETIMEDOUT',
        'ECONNRESET',
        'EADDRINUSE',
        'ECONNREFUSED',
        'EPIPE',
        'ENOTFOUND',
        'ENETUNREACH',
        'EAI_AGAIN',
        'HPE_UNEXPECTED_EOF'
      ]
    }
  });

  console.log(response.body);
} catch (error) {
  console.error('Request failed:', error.message);
}
4Verify server-side response handling

If you control the server, ensure responses are properly formed and connections aren't closed prematurely:

javascript
const http = require('http');

const server = http.createServer((req, res) => {
  // Always set appropriate headers
  res.setHeader('Content-Type', 'application/json');

  const responseData = JSON.stringify({ message: 'Success' });

  // Explicitly set Content-Length
  res.setHeader('Content-Length', Buffer.byteLength(responseData));

  // Ensure complete response is sent before ending
  res.writeHead(200);
  res.end(responseData); // Use end() with data, not separate write() + end()
});

// Handle server errors
server.on('error', (err) => {
  console.error('Server error:', err);
});

// Handle client errors
server.on('clientError', (err, socket) => {
  console.error('Client error:', err);
  // Send proper 400 response instead of abrupt close
  if (socket.writable) {
    socket.end('HTTP/1.1 400 Bad Request\r\n\r\n');
  } else {
    socket.destroy();
  }
});

server.listen(3000);

Avoid closing sockets prematurely:

javascript
// DON'T DO THIS
res.write('Some data');
socket.destroy(); // Abrupt close causes HPE_UNEXPECTED_EOF

// DO THIS INSTEAD
res.write('Some data');
res.end(); // Proper response termination
5Check for proxy or infrastructure issues

If requests pass through proxies, load balancers, or API gateways, verify their timeout configurations:

bash
# Check if proxy is closing connections
curl -v https://api.example.com/endpoint

# Test direct connection bypassing proxy
curl -v --noproxy '*' https://api.example.com/endpoint

For nginx reverse proxy, ensure timeouts are appropriately set:

nginx
# /etc/nginx/nginx.conf
http {
    # Client body timeout
    client_body_timeout 60s;

    # Client header timeout
    client_header_timeout 60s;

    # Keepalive timeout
    keepalive_timeout 65s;

    # Proxy read timeout
    proxy_read_timeout 60s;

    # Proxy connect timeout
    proxy_connect_timeout 60s;

    # Proxy send timeout
    proxy_send_timeout 60s;
}

For AWS Application Load Balancer or API Gateway, verify idle timeout settings are sufficient for your response times.

Advanced notes

HTTP Parser Internals: Node.js uses the llhttp parser (previously http-parser), which is a strict implementation of the HTTP specification. The HPE_UNEXPECTED_EOF error originates from the parser state machine when it's in a state expecting more data (based on Content-Length or chunked encoding) but receives a socket close event instead. The error code HPE stands for "HTTP Parser Error."

Keep-Alive Connection Reuse: A common cause of HPE_UNEXPECTED_EOF is keep-alive connection reuse timing issues. If a server closes an idle keep-alive connection at the exact moment a client tries to reuse it for a new request, the client may send the request header but receive EOF when expecting a response. This is often called the "keep-alive race condition." Modern HTTP clients implement connection health checks or conservative connection reuse strategies to mitigate this.

Chunked Transfer Encoding: When responses use chunked transfer encoding (Transfer-Encoding: chunked), the parser expects each chunk to be formatted as hex-size + CRLF + data + CRLF, terminated by a zero-length chunk (0\r\n\r\n). If the connection closes before this final terminator, HPE_UNEXPECTED_EOF occurs. Ensure your server properly terminates chunked responses.

Content-Length Mismatches: If a server sends a Content-Length header indicating 1000 bytes but only sends 500 bytes before closing the connection, this error will occur. This can happen due to bugs in response generation logic, especially when dynamically calculating response sizes. Always verify Content-Length matches actual body size, or use chunked encoding for dynamic content.

Debugging with Network Traces: Use tools like Wireshark or tcpdump to capture the TCP stream and examine exactly when the FIN packet is sent. This can reveal whether the server is intentionally closing the connection early or if network infrastructure is terminating it:

bash
# Capture HTTP traffic
sudo tcpdump -i any -s 0 -A 'tcp port 80 or tcp port 443' -w capture.pcap

# Analyze with Wireshark or tshark
tshark -r capture.pcap -Y "http" -V

Node.js Agent Connection Pooling: The http.Agent maintains a pool of sockets for reuse. Issues can arise if sockets in the pool become stale. Configure agent socket management:

javascript
const agent = new http.Agent({
  keepAlive: true,
  keepAliveMsecs: 30000,
  maxSockets: 50,
  maxFreeSockets: 10,
  timeout: 60000,
  freeSocketTimeout: 30000 // Close free sockets after 30s
});

Server-Side Prevention: If you're building an HTTP server, use the 'finish' event to ensure responses are fully written before closing:

javascript
res.on('finish', () => {
  console.log('Response fully sent');
});

res.on('close', () => {
  console.log('Connection closed - may indicate client disconnect');
});

Frequently asked questions

What does "HPE_UNEXPECTED_EOF" mean?
js's internal HTTP parser (llhttp) when it encounters an unexpected termination of the HTTP response stream. This error specifically indicates that the connection was closed by the server or network before the HTTP parser could finish reading the complete response based on the Content-Length header or chunked transfer encoding expectations. When an HTTP response is being received, the parser expects certain data patterns—either a specific number of bytes indicated by the Content-Length header, or properly terminated chunked encoding with a final zero-length chunk.
How do I fix "HPE_UNEXPECTED_EOF"?
The HPE_UNEXPECTED_EOF error occurs when Node.js HTTP parser encounters an unexpected end-of-file during HTTP response parsing. This typically happens when the server closes the connection prematurely before sending the complete HTTP response, leaving the client with incomplete data.
What causes "HPE_UNEXPECTED_EOF"?
Server closes the connection before sending the complete response body indicated by Content-Length Network instability or packet loss causes the TCP connection to drop during transmission Server timeout occurs while generating the response, closing the connection mid-stream
Is the "HPE_UNEXPECTED_EOF" error serious?
It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.

Official resources & further reading