How to fix TypeError: readableLength must be a positive integer (stream config) in Node.js

Node.jsINTERMEDIATEMEDIUMUpdated Dec 22, 2025· 138 views

This error occurs when you attempt to configure a Node.js stream with an invalid readableLength value. readableLength must be a positive integer (greater than 0) when specified. Invalid values like negative numbers, zero, strings, or non-integer values will trigger this TypeError.

Quick fix

Fixes ERR_INVALID_OPT_VALUE

// WRONG: readableLength is not a configuration option
const stream = fs.createReadStream('file.txt', { readableLength: 1024 });

// CORRECT: Use highWaterMark to configure buffer threshold
const stream = fs.createReadStream('file.txt', { highWaterMark: 1024 });

// readableLength is used to check current buffer state
stream.on('readable', () => {
  console.log('Current buffered bytes:', stream.readableLength);
});
  1. Verify readableLength is not being used as a stream configuration
  2. Check for readableLength in custom Readable stream implementations
  3. Remove readableLength from stream options objects
  4. Check for type mismatches in configuration values
node.js — error
// WRONG: readableLength is not a configuration option
const stream = fs.createReadStream('file.txt', { readableLength: 1024 });
// CORRECT: Use highWaterMark to configure buffer threshold
const stream = fs.createReadStream('file.txt', { highWaterMark: 1024 });
// readableLength is used to check current buffer state
stream.on('readable', () => {
console.log('Current buffered bytes:', stream.readableLength);
});
TypeError: readableLength must be a positive integer (stream config)

What this error means

The readableLength property in Node.js streams represents the number of bytes currently queued in the stream's internal buffer waiting to be read. While readableLength is typically a read-only property that tracks the current buffer state, if you're setting it as a configuration option during stream creation or in custom stream implementations, it must be a valid positive integer. When passed as a configuration parameter to stream constructors or custom Readable stream implementations, Node.js validates readableLength strictly: it must be a positive whole number (greater than 0, not zero). This is distinct from highWaterMark, which can be 0 or higher. If you pass an invalid value—such as a negative number, zero, a non-integer decimal, a string, null, or undefined—Node.js throws a TypeError to prevent misconfiguration of your stream's buffering behavior. This validation ensures that the stream's internal queue can properly track buffered data and prevent memory issues.

Typical symptoms

  • Application crashes with 'TypeError: readableLength must be a positive integer' during stream creation or configuration
  • Error is thrown when creating custom Readable streams or Transform streams with readableLength option
  • The error appears immediately when initializing streams for file I/O, data transformation, or custom stream implementations
  • Third-party libraries or middleware fail to create streams due to invalid readableLength configuration
  • Error message appears in stream constructor validation, not during runtime data operations

Common causes

  1. Passing zero or a negative number as readableLength (e.g., readableLength: 0 or readableLength: -1024)
  2. Using a non-integer value like a decimal (e.g., readableLength: 1024.5 or readableLength: 512.1)
  3. Accidentally passing a string instead of a number (e.g., readableLength: '1024' instead of readableLength: 1024)
  4. Setting readableLength to null, undefined, or NaN in configuration objects
  5. Dynamically calculating readableLength and ending up with zero, negative, or invalid results due to math errors
  6. Misunderstanding readableLength as a configuration parameter when it should only be used as a read-only property
  7. Copying configuration from another system where the value was stored as a string or incompatible format

How to fix "TypeError: readableLength must be a positive integer (stream config)"

1Verify readableLength is not being used as a stream configuration

Check your stream creation code. readableLength is a read-only property, not typically a configuration option. If you're trying to configure stream buffering, use highWaterMark instead:

javascript
// WRONG: readableLength is not a configuration option
const stream = fs.createReadStream('file.txt', { readableLength: 1024 });

// CORRECT: Use highWaterMark to configure buffer threshold
const stream = fs.createReadStream('file.txt', { highWaterMark: 1024 });

// readableLength is used to check current buffer state
stream.on('readable', () => {
  console.log('Current buffered bytes:', stream.readableLength);
});
2Check for readableLength in custom Readable stream implementations

If implementing a custom Readable stream, verify you're not setting readableLength as a constructor option. It should be managed internally:

javascript
const { Readable } = require('stream');

// WRONG: readableLength is not a valid option in constructor
class CustomReadable extends Readable {
  constructor(options) {
    super(options);
    // Don't set readableLength - it's read-only
  }
}

// CORRECT: Use highWaterMark for configuration
class CustomReadable extends Readable {
  constructor(options = {}) {
    super({
      highWaterMark: options.highWaterMark || 16384,
      encoding: options.encoding,
      objectMode: options.objectMode
    });
    this.dataSource = options.dataSource;
  }

  _read(size) {
    // Read data from source
    const data = this.dataSource.read(size);
    if (data) {
      this.push(data);
    }
  }
}

// Create instance
const readable = new CustomReadable({ highWaterMark: 2048 });

// Check readableLength (read-only property)
readable.on('data', (chunk) => {
  console.log('Bytes buffered:', readable.readableLength);
});
3Remove readableLength from stream options objects

If you're passing a configuration object to stream constructors, remove any readableLength property. Use highWaterMark instead:

javascript
// WRONG: Configuration with readableLength
const streamOptions = {
  encoding: 'utf8',
  readableLength: 4096,  // Invalid configuration
  objectMode: false
};
const stream = fs.createReadStream('file.txt', streamOptions);

// CORRECT: Use highWaterMark for buffering control
const streamOptions = {
  encoding: 'utf8',
  highWaterMark: 4096,  // Controls buffer threshold
  objectMode: false
};
const stream = fs.createReadStream('file.txt', streamOptions);
4Check for type mismatches in configuration values

If reading configuration from environment variables or external sources, ensure numeric values are properly converted. Verify highWaterMark is used instead of readableLength:

javascript
// WRONG: String value and wrong property name
const config = {
  readableLength: '4096',  // String and invalid property
};
const stream = fs.createReadStream('file.txt', config);

// CORRECT: Parse to integer and use highWaterMark
const config = {
  highWaterMark: parseInt(process.env.STREAM_BUFFER || '16384', 10),
};
const stream = fs.createReadStream('file.txt', config);

// CORRECT: Type-safe configuration
function validateStreamConfig(options) {
  if (options.highWaterMark) {
    const hwm = options.highWaterMark;
    if (typeof hwm !== 'number' || !Number.isInteger(hwm) || hwm < 0) {
      throw new TypeError('highWaterMark must be a non-negative integer');
    }
  }
  // Never set readableLength in options
  if (options.readableLength !== undefined) {
    throw new TypeError('readableLength is read-only, use highWaterMark instead');
  }
  return options;
}

const validConfig = validateStreamConfig({
  highWaterMark: 8192,
  encoding: 'utf8'
});
const stream = fs.createReadStream('file.txt', validConfig);
5Monitor readableLength as a read-only property

Use readableLength to inspect the stream's buffer state during operation, but never attempt to set it. This is the correct usage pattern:

javascript
const fs = require('fs');

const stream = fs.createReadStream('large-file.txt', { highWaterMark: 16384 });

// Monitor readableLength (read-only)
stream.on('readable', () => {
  console.log('Bytes waiting to be read:', stream.readableLength);

  // Read data
  let chunk;
  while ((chunk = stream.read()) !== null) {
    console.log('Read', chunk.length, 'bytes');
    console.log('Remaining buffered:', stream.readableLength);
  }
});

// DO NOT attempt to set readableLength
// stream.readableLength = 1024;  // This won't work and may cause issues

stream.on('end', () => {
  console.log('Stream ended');
});

stream.on('error', (error) => {
  console.error('Stream error:', error);
});
6Review third-party library stream configuration

If the error comes from a third-party library, check the library's documentation for correct stream options. Many libraries use highWaterMark, not readableLength:

javascript
// Example: axios with streams
import axios from 'axios';
import fs from 'fs';

// WRONG: Some libraries might accept stream options, but readableLength is invalid
const response = await axios({
  method: 'get',
  url: 'https://example.com/file.bin',
  responseType: 'stream',
  // Don't add readableLength here
});

// CORRECT: Configure stream options properly
const stream = fs.createReadStream('input.txt', {
  highWaterMark: 32768,  // Valid option
  encoding: 'utf8'
});

// If using a custom stream wrapper, ensure it validates options
class StreamWrapper {
  constructor(options = {}) {
    const validOptions = {};

    // Only set valid stream options
    if (options.highWaterMark !== undefined) {
      validOptions.highWaterMark = options.highWaterMark;
    }
    if (options.encoding) {
      validOptions.encoding = options.encoding;
    }

    // Never copy readableLength to stream options
    if (options.readableLength !== undefined) {
      console.warn('readableLength is read-only, ignoring this option');
    }

    this.stream = fs.createReadStream(options.path, validOptions);
  }
}

Advanced notes

Understanding readableLength vs. highWaterMark:
readableLength is always a read-only property that reflects the current number of bytes buffered in the stream's internal queue. highWaterMark is the configuration option that controls the threshold at which the stream pauses reading. These are different concepts: highWaterMark is set once during configuration, while readableLength changes dynamically as data flows through the stream.

Stream Buffering Mechanics:
When you call stream.read(), data is removed from the internal buffer and readableLength decreases accordingly. This is useful for monitoring backpressure conditions: if readableLength approaches highWaterMark, the stream will soon pause reading from its source to prevent memory exhaustion.

Custom Stream Implementations:
If implementing a custom Readable stream by extending the Readable class, manage the internal buffer through the push() method in your _read() implementation. The Node.js stream infrastructure automatically updates readableLength—you should never attempt to set it manually. Always configure highWaterMark in the constructor super() call if custom buffering is needed.

Backpressure Detection:
Use readableLength to detect backpressure conditions and implement adaptive buffering strategies:

javascript
const readable = fs.createReadStream('file.txt', { highWaterMark: 16384 });
const writable = fs.createWriteStream('output.txt');

readable.on('readable', () => {
  let chunk;
  while ((chunk = readable.read()) !== null) {
    const continueWriting = writable.write(chunk);

    // If buffer is growing (backpressure), pause reading
    if (readable.readableLength > readable.readableHighWaterMark) {
      readable.pause();
    }
  }
});

writable.on('drain', () => {
  readable.resume();
});

This pattern is automatically handled by pipe() and stream.pipeline(), which is why those are preferred over manual stream composition for most applications.

Frequently asked questions

What does "ERR_INVALID_OPT_VALUE" mean?
js streams represents the number of bytes currently queued in the stream's internal buffer waiting to be read. While readableLength is typically a read-only property that tracks the current buffer state, if you're setting it as a configuration option during stream creation or in custom stream implementations, it must be a valid positive integer. js validates readableLength strictly: it must be a positive whole number (greater than 0, not zero).
How do I fix "ERR_INVALID_OPT_VALUE"?
This error occurs when you attempt to configure a Node.js stream with an invalid readableLength value. readableLength must be a positive integer (greater than 0) when specified. Invalid values like negative numbers, zero, strings, or non-integer values will trigger this TypeError.
What causes "ERR_INVALID_OPT_VALUE"?
Passing zero or a negative number as readableLength (e.g., readableLength: 0 or readableLength: -1024) Using a non-integer value like a decimal (e.g., readableLength: 1024.5 or readableLength: 512.1) Accidentally passing a string instead of a number (e.g., readableLength: '1024' instead of readableLength: 1024)
Is the "ERR_INVALID_OPT_VALUE" error serious?
It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.

Official resources & further reading