denoland/deno · error · ERR_INVALID_ARG_VALUE

ERR_INVALID_ARG_VALUE

ERR_INVALID_ARG_VALUE

Error message

The property 'input.escapeCodeTimeout' is invalid. Received ${this.escapeCodeTimeout}

What it means

readline.createInterface requires options.escapeCodeTimeout to be a finite number when provided (it is the ms delay waiting for an escape-sequence, default 500). Number.isFinite(input.escapeCodeTimeout) failing — NaN, Infinity, or any non-number including strings — throws ERR_INVALID_ARG_VALUE('input.escapeCodeTimeout'). Note the Deno polyfill reports this.escapeCodeTimeout (still the default 500 at that point) in the message, so 'Received 500' does not reflect the value you actually passed.

Source

Thrown at ext/node/polyfills/internal/readline/interface.mjs:209

    output = input.output;
    completer = input.completer;
    terminal = input.terminal;
    history = input.history;
    historySize = input.historySize;
    signal = input.signal;
    if (input.tabSize !== undefined) {
      validateUint32(input.tabSize, "tabSize", true);
      this.tabSize = input.tabSize;
    }
    removeHistoryDuplicates = input.removeHistoryDuplicates;
    if (input.prompt !== undefined) {
      prompt = input.prompt;
    }
    if (input.escapeCodeTimeout !== undefined) {
      if (NumberIsFinite(input.escapeCodeTimeout)) {
        this.escapeCodeTimeout = input.escapeCodeTimeout;
      } else {
        throw new ERR_INVALID_ARG_VALUE(
          "input.escapeCodeTimeout",
          this.escapeCodeTimeout,
        );
      }
    }

    if (signal) {
      validateAbortSignal(signal, "options.signal");
    }

    crlfDelay = input.crlfDelay;
    input = input.input;
  }

  if (completer !== undefined && typeof completer !== "function") {
    throw new ERR_INVALID_ARG_VALUE("completer", completer);
  }

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Pass a plain finite number: escapeCodeTimeout: 1000
  2. Coerce from config: Number(cfg.escapeCodeTimeout) and check Number.isFinite before passing
  3. Omit the option entirely to keep the 500 ms default

Example fix

// before
createInterface({ input, escapeCodeTimeout: Number.POSITIVE_INFINITY });

// after
createInterface({ input, escapeCodeTimeout: 1000 });
Defensive patterns

Strategy: validation

Validate before calling

function makeRl(input: NodeJS.ReadableStream, opts: Record<string, unknown>) {
  const t = opts.escapeCodeTimeout;
  return readline.createInterface({
    input,
    ...(Number.isFinite(t) ? { escapeCodeTimeout: t as number } : {}),
  });
}

Type guard

const isFiniteNumber = (v: unknown): v is number =>
  typeof v === 'number' && Number.isFinite(v);

Try / catch

try {
  rl = readline.createInterface({ input, escapeCodeTimeout: t } as readline.ReadLineOptions);
} catch (err) {
  if (err?.code === 'ERR_INVALID_ARG_VALUE' && /escapeCodeTimeout/.test(err.message)) {
    rl = readline.createInterface({ input }); // default 500ms
  } else throw err;
}

Prevention

When it happens

Trigger: createInterface({ input, escapeCodeTimeout: Infinity }); passing '500' as a string from config; computing the value as a division that yields NaN or Infinity.

Common situations: Tuning escape-code timing for slow SSH/telnet terminals; values read from env vars or JSON config that arrive as strings; reusing a timeout constant that was set to Infinity elsewhere.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20). Data as JSON: /api/errors/158b9aa63a2ee51e. Report an issue: GitHub.