oven-sh/bun · error · Error

${where}: cannot parse param `${raw}`

Error message

${where}: cannot parse param `${raw}`

What it means

The HOST_EXPORT signature parser in generate-host-exports.ts expects every parameter to have the `name: Type` form and splits on top-level commas. This error fires for a parameter with no colon — most commonly a bare `self` receiver, a bare type, or a typo like a missing colon. The message includes the parsing location (`${where}`) and the exact offending text so the call site can be found immediately.

Source

Thrown at src/codegen/generate-host-exports.ts:166

  let depth = 0,
    start = 0;
  for (let i = 0; i < list.length; i++) {
    const c = list[i];
    if (c === "<" || c === "(" || c === "[") depth++;
    else if (c === ">" || c === ")" || c === "]") depth--;
    else if (c === "," && depth === 0) {
      parts.push(list.slice(start, i));
      start = i + 1;
    }
  }
  if (start < list.length) parts.push(list.slice(start));
  return parts
    .map(p => p.trim())
    .filter(Boolean)
    .map((raw, i) => {
      // `name: Type` — strip leading `mut ` / `_` patterns.
      const colon = raw.indexOf(":");
      if (colon < 0) throw new Error(`${where}: cannot parse param \`${raw}\``);
      let name = raw
        .slice(0, colon)
        .trim()
        .replace(/^mut\s+/, "");
      // Only the bare `_` pattern is not a usable identifier; `_foo` is valid
      // and intentionally documentary — keep it.
      if (name === "_") name = `_a${i}`;
      const ty = raw.slice(colon + 1).trim();
      const { cTy, deref } = ptrify(ty);
      return { raw, name, ty, cTy, callExpr: deref(name) };
    });
}

const exportsFound: Export[] = [];
const errors: string[] = [];
const seenSymbols = new Map<string, string>();

for (const { dir, crate } of scanRoots) {

View on GitHub (pinned to 8c5296ac45)

Solutions

  1. Locate the function via the `${where}` location in the message and look at the exact `${raw}` text quoted
  2. If it is `self`, write it explicitly as `_self: &Foo` (or `*const Foo`), or move the body into a free `pub fn` taking the handle as its first named parameter
  3. Ensure every parameter is `name: Type` with no nested unbalanced parens/angles that confuse the comma splitter

Example fix

// before
// HOST_EXPORT(FooDoThing)
pub fn do_thing(self, amount: u32) -> JSValue { ... }

// after
// HOST_EXPORT(FooDoThing)
pub fn do_thing(_self: &Foo, amount: u32) -> JSValue { ... }
Defensive patterns

Strategy: validation

Validate before calling

// each param of a HOST_EXPORT fn must be `name: Type`
function paramsParse(params: string): boolean {
  return params.split(",").every(p => {
    const t = p.trim();
    return !t || /:[^:]/.test(t);
  });
}

Prevention

When it happens

Trigger: Marking a method (not a free function) with `// HOST_EXPORT(...)`: its `self` parameter has no `name: Type` colon form; or a parameter written as just a type name; or a multi-line param list where a stray comma produces an empty/odd fragment.

Common situations: Trying to export an inherent method directly instead of a free wrapper function; hand-editing param lists and dropping a colon.

Related errors


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