{"record":{"id":"93c28329f29e6254","repo":"oven-sh/bun","slug":"generate-string-map-name-emitcaseinsensitive","errorCode":null,"errorMessage":"generate-string-map: ${name}: emitCaseInsensitive requires ASCII keys; ${JSON.stringify(k)} is not","messagePattern":"generate-string-map: (.+?): emitCaseInsensitive requires ASCII keys; (.+?) is not","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/codegen/generate-string-map.ts","lineNumber":228,"sourceCode":"  }\n  out.push(`        _ => None,`);\n  out.push(`    }`);\n  out.push(`}`);\n}\n\nfunction buildOne<V>(spec: StringMapSpec<V>): string {\n  const { name, valueTy, entries, emitKeys, emitIndexOf, emitCaseInsensitive, doc } = spec;\n  const emitValue = spec.emitValue ?? ((v: V) => (typeof v === \"string\" ? JSON.stringify(v) : String(v)));\n\n  const seen = new Set<string>();\n  const seenCi = new Set<string>();\n  for (const [k] of entries) {\n    if (seen.has(k)) throw new Error(`generate-string-map: duplicate key ${JSON.stringify(k)} in ${name}`);\n    seen.add(k);\n    if (emitCaseInsensitive) {\n      // eslint-disable-next-line no-control-regex\n      if (!/^[\\x00-\\x7f]*$/.test(k)) {\n        throw new Error(\n          `generate-string-map: ${name}: emitCaseInsensitive requires ASCII keys; ${JSON.stringify(k)} is not`,\n        );\n      }\n      const lk = k.toLowerCase();\n      if (seenCi.has(lk)) {\n        throw new Error(`generate-string-map: ${name}: keys ${JSON.stringify(k)} collide under case folding`);\n      }\n      seenCi.add(lk);\n    }\n  }\n\n  const kvs: Array<readonly [Buffer, string]> = entries.map(([k, v]) => [Buffer.from(k, \"utf8\"), emitValue(v)]);\n  const out: string[] = [];\n  if (doc) for (const line of doc.split(\"\\n\")) out.push(`/// ${line}`.trimEnd());\n  emitLookup(out, name, valueTy, kvs, { ci: false });\n\n  if (emitCaseInsensitive) {\n    out.push(``);","sourceCodeStart":210,"sourceCodeEnd":246,"githubUrl":"https://github.com/oven-sh/bun/blob/8c5296ac459e8252d3cd702f3fbcbb0c249d95d5/src/codegen/generate-string-map.ts#L210-L246","documentation":"When a string-map spec sets `emitCaseInsensitive: true`, the generator also emits a `<name>_ignore_ascii_case` lookup that relies on ASCII-only case folding. The generator therefore validates every key against /^[\\x00-\\x7f]*$/ and refuses non-ASCII keys, because ASCII case folding would leave non-ASCII bytes uncomparable and produce a subtly broken lookup.","triggerScenarios":"A spec with `emitCaseInsensitive: true` whose entries contain any character above U+007F (e.g. \"café\", \" size\", a non-breaking space) or control characters outside the allowed range.","commonSituations":"Copying keys from a spec file saved with smart quotes, adding localized/unicode header or flag names to a case-insensitive lookup table.","solutions":["Replace the non-ASCII key the message prints with its pure-ASCII equivalent.","If unicode keys are required, set `emitCaseInsensitive: false` and rely on the exact-match lookup only.","Split the map: ASCII keys in the case-insensitive map, unicode keys in a separate exact-match map."],"exampleFix":"// before\nexport default {\n  name: \"Header\",\n  emitCaseInsensitive: true,\n  entries: [[\"café\", 1]],\n};\n\n// after\nexport default {\n  name: \"Header\",\n  emitCaseInsensitive: true,\n  entries: [[\"cafe\", 1]],\n};","handlingStrategy":"validation","validationCode":"const isAsciiKey = k => /^[\\x00-\\x7f]*$/.test(k);\nfunction assertAsciiKeys(name, entries, emitCaseInsensitive) {\n  if (!emitCaseInsensitive) return;\n  for (const [k] of entries) {\n    if (!isAsciiKey(k)) throw new Error(`${name}: non-ASCII key ${JSON.stringify(k)} needs emitCaseInsensitive:false`);\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Decide up front whether a map needs case-insensitive matching; if yes, restrict its vocabulary to ASCII.","Add an editor/CI ASCII check on *.string-map.ts files.","Watch for invisible non-ASCII characters (smart quotes, NBSP) when pasting keys."],"tags":["codegen","string-map","ascii","unicode"],"backgroundTag":null,"analyzedSha":"8c5296ac459e8252d3cd702f3fbcbb0c249d95d5","analyzedAt":"2026-08-16T08:01:58.794Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}