oven-sh/bun · error · Error

Call is not known at bundle-time: '$$${name}${inner.result}'

Error message

Call is not known at bundle-time: '$$${name}${inner.result}'

What it means

The builtin-module preprocessor evaluates $rust/$cpp/$newRustFunction/$newCppFunction calls at bundle time: it slices out the argument text, converts single quotes to double quotes, and JSON.parses it. These macros register native FFI functions and must take literal arguments; if the slice is not parseable JSON (template literals, variables, escapes that break quoting), the call is not statically known and codegen throws.

Source

Thrown at src/codegen/replacements.ts:249

        true,
      ];
    } else if (["rust", "cpp", "newRustFunction", "newCppFunction"].includes(name)) {
      const kind = name.includes("ust") ? "rust" : "cpp";
      const is_create_fn = name.startsWith("new");

      const inner = sliceSourceCode(rest, true);
      let args;
      try {
        const str =
          "[" +
          inner.result
            .slice(1, -1)
            .replaceAll("'", '"')
            .replace(/,[\s\n]*$/s, "") +
          "]";
        args = JSON.parse(str);
      } catch {
        throw new Error(`Call is not known at bundle-time: '$${name}${inner.result}'`);
      }
      if (
        args.length != (is_create_fn ? 3 : 2) ||
        typeof args[0] !== "string" ||
        typeof args[1] !== "string" ||
        (is_create_fn && typeof args[2] !== "number")
      ) {
        if (is_create_fn) {
          throw new Error(`$${name} takes three arguments, but got '$${name}${inner.result}'`);
        } else {
          throw new Error(`$${name} takes two string arguments, but got '$${name}${inner.result}'`);
        }
      }

      const id = registerNativeCall(kind, args[0], args[1], is_create_fn ? args[2] : null);

      return [slice.slice(0, match.index) + "__intrinsic__lazy(" + id + ")", inner.rest, true];
    } else if (name === "isPromiseFulfilled" || name === "isPromiseRejected" || name === "isPromisePending") {

View on GitHub (pinned to 8c5296ac45)

Solutions

  1. Inline the arguments as literals: $rust("StructName", "functionName").
  2. Use single-quoted or plain double-quoted strings without internal double quotes; escape any nested quotes as \".
  3. Do not wrap macro arguments in template literals or pass variables — the bundler cannot evaluate them.

Example fix

// before
const s = "BunObject";
const fn = $rust(s, "open");

// after
const fn = $rust("BunObject", "open");
Defensive patterns

Strategy: validation

Validate before calling

const macroCallRe = /\$\w+\s*\(/g;
const literalArgsRe = /^\$\w+\(\s*(['"][^'"]*['"]\s*(,\s*['"][^'"]*['"]\s*)*)?\)$/;
for (const line of builtinSource.split("\n")) {
  if (macroCallRe.test(line) && !literalArgsRe.test(line.trim())) {
    console.warn(`check macro call uses only literal args: ${line.trim()}`);
  }
}

Prevention

When it happens

Trigger: Calling $rust(...) / $cpp(...) / $newRustFunction(...) inside src/js with anything except plain string/number literals — e.g. `const n = "Bun"; $rust(n, "open")`, backtick strings, or strings containing unescaped double quotes.

Common situations: Refactoring builtin code to hoist the struct/function names into constants; adding a new $rust binding and pasting a template-literal call site.

Related errors


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