denoland/deno · error · TypeError

Invalid status text: "${init.statusText}"

Error message

Invalid status text: "${init.statusText}"

What it means

initializeAResponse validates a non-empty init.statusText against REASON_PHRASE_RE (printable ASCII reason-phrase characters; control bytes and non-ASCII such as \n, \r, or UTF-8 multibyte characters fail). A mismatch throws TypeError 'Invalid status text: "<value>"'.

Source

Thrown at ext/fetch/23_response.js:528

  response,
  init,
  bodyWithType,
  prefix,
  context,
) {
  // 1.
  if ((init.status < 200 || init.status > 599) && init.status != 101) {
    throw new RangeError(
      `The status provided (${init.status}) is not equal to 101 and outside the range [200, 599]`,
    );
  }

  // 2.
  if (
    init.statusText &&
    RegExpPrototypeExec(REASON_PHRASE_RE, init.statusText) === null
  ) {
    throw new TypeError(
      `Invalid status text: "${init.statusText}"`,
    );
  }

  // 3.
  response[_response].status = init.status;

  // 4.
  response[_response].statusMessage = init.statusText;
  // 5.
  if (init.headers !== undefined) {
    const list = responseHeaderList(response);
    if (
      !tryFillSingleContentTypeHeader(
        list,
        init.headers,
      )
    ) {

View on GitHub (pinned to 89f33cbef2)

Solutions

  1. Keep statusText to plain printable ASCII (or omit it — the standard phrase is used)
  2. Move rich messages into the JSON body or a custom header
  3. Sanitize: statusText.replace(/[^\x20-\x7e\t]/g, '') before passing it

Example fix

// before
return new Response(null, {
  status: 400,
  statusText: 'Bad Request — missing id', // em dash is invalid
});

// after
return Response.json({ error: 'Bad Request: missing id' }, { status: 400 });
Defensive patterns

Strategy: validation

Validate before calling

const REASON_PHRASE = /^[\x09\x20-\x7e\x80-\xff]*$/; // be conservative: ASCII only
function sanitizeStatusText(text) {
  const t = String(text ?? '');
  return /^[\x20-\x7e\t]*$/.test(t) ? t : '';
}

Type guard

const isValidStatusText = (t) =>
  t == null || t === '' || /^[\x09\x20-\x7e]+$/.test(String(t));

Prevention

When it happens

Trigger: new Response(body, { status: 200, statusText: 'OK\n' }), statusText containing '\r', or a message with emoji/accented characters; statusText built by string interpolation of unsanitized data.

Common situations: Putting human-readable error messages (with punctuation like non-ASCII quotes or emoji) into statusText instead of the body; header-injection-style input flowing into statusText.

Related errors


AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16). Data as JSON: /api/errors/aaefee41c809b22a. Report an issue: GitHub.