oven-sh/bun · error · Error
generate-string-map: ${name}: emitCaseInsensitive requires A
Error message
generate-string-map: ${name}: emitCaseInsensitive requires ASCII keys; ${JSON.stringify(k)} is not What it means
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.
Source
Thrown at src/codegen/generate-string-map.ts:228
}
out.push(` _ => None,`);
out.push(` }`);
out.push(`}`);
}
function buildOne<V>(spec: StringMapSpec<V>): string {
const { name, valueTy, entries, emitKeys, emitIndexOf, emitCaseInsensitive, doc } = spec;
const emitValue = spec.emitValue ?? ((v: V) => (typeof v === "string" ? JSON.stringify(v) : String(v)));
const seen = new Set<string>();
const seenCi = new Set<string>();
for (const [k] of entries) {
if (seen.has(k)) throw new Error(`generate-string-map: duplicate key ${JSON.stringify(k)} in ${name}`);
seen.add(k);
if (emitCaseInsensitive) {
// eslint-disable-next-line no-control-regex
if (!/^[\x00-\x7f]*$/.test(k)) {
throw new Error(
`generate-string-map: ${name}: emitCaseInsensitive requires ASCII keys; ${JSON.stringify(k)} is not`,
);
}
const lk = k.toLowerCase();
if (seenCi.has(lk)) {
throw new Error(`generate-string-map: ${name}: keys ${JSON.stringify(k)} collide under case folding`);
}
seenCi.add(lk);
}
}
const kvs: Array<readonly [Buffer, string]> = entries.map(([k, v]) => [Buffer.from(k, "utf8"), emitValue(v)]);
const out: string[] = [];
if (doc) for (const line of doc.split("\n")) out.push(`/// ${line}`.trimEnd());
emitLookup(out, name, valueTy, kvs, { ci: false });
if (emitCaseInsensitive) {
out.push(``);View on GitHub (pinned to 8c5296ac45)
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.
Example fix
// before
export default {
name: "Header",
emitCaseInsensitive: true,
entries: [["café", 1]],
};
// after
export default {
name: "Header",
emitCaseInsensitive: true,
entries: [["cafe", 1]],
}; Defensive patterns
Strategy: validation
Validate before calling
const isAsciiKey = k => /^[\x00-\x7f]*$/.test(k);
function assertAsciiKeys(name, entries, emitCaseInsensitive) {
if (!emitCaseInsensitive) return;
for (const [k] of entries) {
if (!isAsciiKey(k)) throw new Error(`${name}: non-ASCII key ${JSON.stringify(k)} needs emitCaseInsensitive:false`);
}
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: Copying keys from a spec file saved with smart quotes, adding localized/unicode header or flag names to a case-insensitive lookup table.
Related errors
- generate-string-map: duplicate key ${JSON.stringify(k)} in $
- generate-string-map: ${name}: keys ${JSON.stringify(k)} coll
- ${name}: ${entries.length} entries exceed u16 indexOf range
- ${input}: missing default export
- non-ascii character in string "${str}". this will not be a v
AI-assisted analysis of oven-sh/bun@8c5296ac45 (2026-08-16).
Data as JSON: /api/errors/93c28329f29e6254.
Report an issue: GitHub.