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.

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.

Appendix: 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)