{"record":{"id":"f742524457899311","repo":"different-ai/openwork","slug":"string-normalize-expects-the-form-nfc-nfd-n","errorCode":null,"errorMessage":"String.normalize expects the form \"NFC\", \"NFD\", \"NFKC\", or \"NFKD\" (got ${JSON.stringify(form)}).","messagePattern":"String\\.normalize expects the form \"NFC\", \"NFD\", \"NFKC\", or \"NFKD\" \\(got (.+?)\\)\\.","errorType":"exception","errorClass":"InterpreterRuntimeError","httpStatus":null,"severity":"error","filePath":"packages/codemode/src/interpreter/runtime.ts","lineNumber":382,"sourceCode":"    case \"trimStart\":\n    case \"trimLeft\":\n      result = value.trimStart()\n      break\n    case \"trimEnd\":\n    case \"trimRight\":\n      result = value.trimEnd()\n      break\n    // Locale/options arguments are ignored: comparison runs with the host default locale, and\n    // the common use is a sort comparator where any consistent order works.\n    case \"localeCompare\":\n      result = value.localeCompare(str(0))\n      break\n    case \"normalize\": {\n      const form = optStr(0)\n      try {\n        result = value.normalize(form)\n      } catch {\n        throw new InterpreterRuntimeError(\n          `String.normalize expects the form \"NFC\", \"NFD\", \"NFKC\", or \"NFKD\" (got ${JSON.stringify(form)}).`,\n          node,\n        ).as(\"RangeError\")\n      }\n      break\n    }\n    case \"split\": {\n      if (args.length === 0) {\n        result = [value]\n        break\n      }\n      if (args[0] instanceof SandboxRegExp) {\n        result = value.split((args[0] as SandboxRegExp).regex, optNum(1))\n        break\n      }\n      const requestedLimit = optNum(1)\n      result = value.split(str(0), requestedLimit === undefined ? undefined : requestedLimit >>> 0)\n      break","sourceCodeStart":364,"sourceCodeEnd":400,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/packages/codemode/src/interpreter/runtime.ts#L364-L400","documentation":"String.normalize only accepts Unicode normalization forms NFC, NFD, NFKC, or NFKD; the host engine throws a RangeError for anything else. The sandbox catches that RangeError and rethrows it as an InterpreterRuntimeError tagged .as(\"RangeError\") with a message showing the JSON-encoded bad form. Passing undefined is allowed (defaults to NFC).","triggerScenarios":"Calling String('e').normalize('nfc') (lowercase), normalize('NFc'), normalize(''), normalize(null), or normalize of any string other than the exact four forms; note normalize(undefined) is fine via optStr but normalize(null) reaches the host as null and throws.","commonSituations":"Typo'd or lowercase form names; building the form dynamically from config/CLI flags; passing null from optional JSON fields expecting it to mean default; localizing code that used a locale-specific argument.","solutions":["Use exactly one of \"NFC\", \"NFD\", \"NFKC\", \"NFKD\" (case-sensitive, uppercase)","Guard optional config values with form === undefined ? undefined : form.toUpperCase() and validate membership in the set","Replace null with undefined (or omit the argument) so optStr treats it as the default NFC","Verify the value is a string, not a number or object"],"exampleFix":"// before\ntext.normalize(form) // form = \"nfc\"\n// after\nconst FORMS = [\"NFC\", \"NFD\", \"NFKC\", \"NFKD\"]\ntext.normalize(FORMS.includes(form) ? form : undefined)","handlingStrategy":"validation","validationCode":"const FORMS = new Set([\"NFC\", \"NFD\", \"NFKC\", \"NFKD\"])\nif (form !== undefined && !FORMS.has(form)) throw new TypeError(`normalize form must be one of ${[...FORMS]}, got ${JSON.stringify(form)}`)\ntext.normalize(form)","typeGuard":"const isNormForm = (v) => v === undefined || [\"NFC\",\"NFD\",\"NFKC\",\"NFKD\"].includes(v)","tryCatchPattern":"try { out = text.normalize(form) } catch (e) { if (String(e.message).includes(\"String.normalize\")) out = text.normalize(); else throw e }","preventionTips":["Only pass the exact uppercase form strings","Treat undefined as the default, not null","Normalize/validate form values coming from config before use","Avoid dynamic construction of the form name"],"tags":["codemode","interpreter","range-error","unicode","string-methods"],"backgroundTag":"invalid-enum-value","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}