Skip to content

HEAD route throws ERR_INVALID_ARG_TYPE error when GET route sends a Web Stream #6371

@orionmiz

Description

@orionmiz

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the bug has not already been reported

Fastify version

5.6.1

Plugin version

No response

Node.js version

22.18.0

Operating system

macOS

Operating system version (i.e. 20.04, 11.3, 10)

15.6

Description

Summary

Fastify automatically creates a corresponding HEAD route for every GET route. However, if the GET route handler sends a Web Stream (e.g., a ReadableStream), making a request to the HEAD route throws a TypeError.

Steps to Reproduce

  1. Register a GET route that replies with a Web Stream payload (e.g., new ReadableStream(...)).
  2. Start the Fastify server.
  3. Send a HEAD request to the same route.
  4. The server crashes with the error below.

Error Details

The following TypeError is thrown:

TypeError [ERR_INVALID_ARG_TYPE]: The "string" argument must be of type string or an instance of Buffer or ArrayBuffer. Received an instance of ReadableStream
    at Function.byteLength (node:buffer:777:11)
    ...

Analysis

This error originates from the headRouteOnSendHandler function, specifically at this line:

const size = '' + Buffer.byteLength(payload)

This line incorrectly assumes the payload is a Buffer-like type (string, Buffer, or ArrayBuffer, ...) to calculate the Content-Length.
Thus Buffer.byteLength fails causing the error when the payload is a ReadableStream.

Link to code that reproduces the bug

https://github.com/orionmiz/fastify-repro-web-stream-in-head

Expected Behavior

HEAD request to a route whose corresponding GET handler sends a Web Stream should not throw an error.

  • The headRouteOnSendHandler should not attempt to calculate the Content-Length of a stream payload (e.g., by calling Buffer.byteLength).
  • Instead, in accordance with the HTTP specification, the HEAD response must include the exact same headers (such as Transfer-Encoding or Content-Length) that would have been sent by the corresponding GET request.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions