{"record":{"id":"aaefee41c809b22a","repo":"denoland/deno","slug":"invalid-status-text-init-statustext","errorCode":null,"errorMessage":"Invalid status text: \"${init.statusText}\"","messagePattern":"Invalid status text: \"(.+?)\"","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/fetch/23_response.js","lineNumber":528,"sourceCode":"  response,\n  init,\n  bodyWithType,\n  prefix,\n  context,\n) {\n  // 1.\n  if ((init.status < 200 || init.status > 599) && init.status != 101) {\n    throw new RangeError(\n      `The status provided (${init.status}) is not equal to 101 and outside the range [200, 599]`,\n    );\n  }\n\n  // 2.\n  if (\n    init.statusText &&\n    RegExpPrototypeExec(REASON_PHRASE_RE, init.statusText) === null\n  ) {\n    throw new TypeError(\n      `Invalid status text: \"${init.statusText}\"`,\n    );\n  }\n\n  // 3.\n  response[_response].status = init.status;\n\n  // 4.\n  response[_response].statusMessage = init.statusText;\n  // 5.\n  if (init.headers !== undefined) {\n    const list = responseHeaderList(response);\n    if (\n      !tryFillSingleContentTypeHeader(\n        list,\n        init.headers,\n      )\n    ) {","sourceCodeStart":510,"sourceCodeEnd":546,"githubUrl":"https://github.com/denoland/deno/blob/89f33cbef296a2b287f323d42de54c871fa69c77/ext/fetch/23_response.js#L510-L546","documentation":"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>\"'.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Keep statusText to plain printable ASCII (or omit it — the standard phrase is used)","Move rich messages into the JSON body or a custom header","Sanitize: statusText.replace(/[^\\x20-\\x7e\\t]/g, '') before passing it"],"exampleFix":"// before\nreturn new Response(null, {\n  status: 400,\n  statusText: 'Bad Request — missing id', // em dash is invalid\n});\n\n// after\nreturn Response.json({ error: 'Bad Request: missing id' }, { status: 400 });","handlingStrategy":"validation","validationCode":"const REASON_PHRASE = /^[\\x09\\x20-\\x7e\\x80-\\xff]*$/; // be conservative: ASCII only\nfunction sanitizeStatusText(text) {\n  const t = String(text ?? '');\n  return /^[\\x20-\\x7e\\t]*$/.test(t) ? t : '';\n}","typeGuard":"const isValidStatusText = (t) =>\n  t == null || t === '' || /^[\\x09\\x20-\\x7e]+$/.test(String(t));","tryCatchPattern":null,"preventionTips":["Keep statusText to printable ASCII; put detail in the body","Strip control characters and non-ASCII from interpolated messages","Prefer Response.json({ error }) over custom status phrases"],"tags":["fetch","response","status-text","validation"],"backgroundTag":null,"analyzedSha":"89f33cbef296a2b287f323d42de54c871fa69c77","analyzedAt":"2026-08-16T07:54:21.310Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}