{"record":{"id":"c901dfb0136cd24e","repo":"oven-sh/bun","slug":"where-cannot-parse-param-raw","errorCode":null,"errorMessage":"${where}: cannot parse param `${raw}`","messagePattern":"(.+?): cannot parse param `(.+?)`","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/codegen/generate-host-exports.ts","lineNumber":166,"sourceCode":"  let depth = 0,\n    start = 0;\n  for (let i = 0; i < list.length; i++) {\n    const c = list[i];\n    if (c === \"<\" || c === \"(\" || c === \"[\") depth++;\n    else if (c === \">\" || c === \")\" || c === \"]\") depth--;\n    else if (c === \",\" && depth === 0) {\n      parts.push(list.slice(start, i));\n      start = i + 1;\n    }\n  }\n  if (start < list.length) parts.push(list.slice(start));\n  return parts\n    .map(p => p.trim())\n    .filter(Boolean)\n    .map((raw, i) => {\n      // `name: Type` — strip leading `mut ` / `_` patterns.\n      const colon = raw.indexOf(\":\");\n      if (colon < 0) throw new Error(`${where}: cannot parse param \\`${raw}\\``);\n      let name = raw\n        .slice(0, colon)\n        .trim()\n        .replace(/^mut\\s+/, \"\");\n      // Only the bare `_` pattern is not a usable identifier; `_foo` is valid\n      // and intentionally documentary — keep it.\n      if (name === \"_\") name = `_a${i}`;\n      const ty = raw.slice(colon + 1).trim();\n      const { cTy, deref } = ptrify(ty);\n      return { raw, name, ty, cTy, callExpr: deref(name) };\n    });\n}\n\nconst exportsFound: Export[] = [];\nconst errors: string[] = [];\nconst seenSymbols = new Map<string, string>();\n\nfor (const { dir, crate } of scanRoots) {","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/oven-sh/bun/blob/8c5296ac459e8252d3cd702f3fbcbb0c249d95d5/src/codegen/generate-host-exports.ts#L148-L184","documentation":"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.","triggerScenarios":"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.","commonSituations":"Trying to export an inherent method directly instead of a free wrapper function; hand-editing param lists and dropping a colon.","solutions":["Locate the function via the `${where}` location in the message and look at the exact `${raw}` text quoted","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","Ensure every parameter is `name: Type` with no nested unbalanced parens/angles that confuse the comma splitter"],"exampleFix":"// before\n// HOST_EXPORT(FooDoThing)\npub fn do_thing(self, amount: u32) -> JSValue { ... }\n\n// after\n// HOST_EXPORT(FooDoThing)\npub fn do_thing(_self: &Foo, amount: u32) -> JSValue { ... }","handlingStrategy":"validation","validationCode":"// each param of a HOST_EXPORT fn must be `name: Type`\nfunction paramsParse(params: string): boolean {\n  return params.split(\",\").every(p => {\n    const t = p.trim();\n    return !t || /:[^:]/.test(t);\n  });\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never mark inherent methods (`self`) for HOST_EXPORT — export free functions taking an explicit handle parameter","Write `_self: &T` (or `*const T`) instead of a bare `self` in any exported signature"],"tags":["ffi","codegen","rust","parsing"],"backgroundTag":null,"analyzedSha":"8c5296ac459e8252d3cd702f3fbcbb0c249d95d5","analyzedAt":"2026-08-16T08:01:58.794Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}