oven-sh/bun · error · Error

non-ascii character in string "${str}". this will not be a v

Error message

non-ascii character in string "${str}". this will not be a valid ASCIILiteral

What it means

checkAscii (src/codegen/helpers.ts) guards strings that codegen embeds as C++ ASCIILiteral byte arrays — bundle-modules.ts checks the generated module source (line 425) and bundle-functions.ts checks each function source (line 405). A non-ASCII character would corrupt the generated literal (byte length != character length), so it throws before writing broken output.

Source

Thrown at src/codegen/helpers.ts:35

export function readdirRecursive(root: string): string[] {
  const files = fs.readdirSync(root, { withFileTypes: true });
  return files.flatMap(file => {
    const fullPath = path.join(root, file.name);
    return file.isDirectory() ? readdirRecursive(fullPath) : fullPath;
  });
}

export function resolveSyncOrNull(specifier: string, from: string) {
  try {
    return Bun.resolveSync(specifier, from);
  } catch {
    return null;
  }
}

export function checkAscii(str: string) {
  if (!isAscii(Buffer.from(str))) {
    throw new Error(`non-ascii character in string "${str}". this will not be a valid ASCIILiteral`);
  }

  return str;
}

export function writeIfNotChanged(file: string, contents: string) {
  if (Array.isArray(contents)) contents = contents.join("");
  contents = contents.replaceAll("\r\n", "\n").trim() + "\n";

  try {
    const oldContents = fs.readFileSync(file, "utf8");
    if (oldContents === contents) {
      return;
    }
  } catch (e) {}

  try {
    fs.writeFileSync(file, contents);

View on GitHub (pinned to 8c5296ac45)

Solutions

  1. Replace the character the message prints with an ASCII equivalent or a \uXXXX escape in the JS source.
  2. Keep builtin module files ASCII-only (configure your editor / add an editorconfig `charset` check).
  3. If unicode is required at runtime, encode it as an escape sequence so the literal bytes stay ASCII.

Example fix

// before (src/js/builtins file)
export const msg = "unexpected value”; // smart quote is non-ASCII

// after
export const msg = "unexpected value";
Defensive patterns

Strategy: validation

Validate before calling

import { isAscii } from "node:buffer";
function assertAsciiLiteral(s: string, where: string) {
  if (!isAscii(Buffer.from(s))) {
    const bad = [...s].find(ch => ch.charCodeAt(0) > 0x7f);
    throw new Error(`${where}: non-ASCII character ${JSON.stringify(bad)} — use \\u escapes`);
  }
}

Type guard

const isAsciiLiteral = (s: string) => isAscii(Buffer.from(s));

Prevention

When it happens

Trigger: Adding a builtin JS module or function under src/js whose source contains a non-ASCII character (unicode strings, smart quotes, non-ASCII identifiers) that ends up in the embedded literal.

Common situations: Copy-pasting code with typographic quotes or accented words into src/js builtins; pasting a unicode arrow or emoji into an error message of a builtin.

Related errors


AI-assisted analysis of oven-sh/bun@8c5296ac45 (2026-08-16). Data as JSON: /api/errors/ee8eb3ae6785ae5d. Report an issue: GitHub.