{"record":{"id":"fbeefe5d8e3e98ed","repo":"dotnet/runtime","slug":"cwrap-name-not-found-or-not-a-function","errorCode":null,"errorMessage":"cwrap ${name} not found or not a function","messagePattern":"cwrap (.+?) not found or not a function","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/mono/browser/runtime/cwraps.ts","lineNumber":308,"sourceCode":"            // Module[\"wasmExports\"] may not be defined yet if we are early enough in the startup process\n            //  in that case, we need to rely on emscripten's lazy wrappers\n            Module[\"wasmExports\"]\n            ? <Function>((<any>Module[\"wasmExports\"])[name])\n            : undefined;\n\n    // If the argument count for the wasm function doesn't match the signature, fall back to cwrap\n    if (fce && argTypes && (fce.length !== argTypes.length)) {\n        mono_log_error(`argument count mismatch for cwrap ${name}`);\n        fce = undefined;\n    }\n\n    // We either failed to find the raw wasm func or for some reason we can't use it directly\n    if (typeof (fce) !== \"function\")\n        fce = Module.cwrap(name, returnType, argTypes, opts);\n\n    if (typeof (fce) !== \"function\") {\n        const msg = `cwrap ${name} not found or not a function`;\n        throw new Error(msg);\n    }\n    return fce;\n}\n\nexport function init_c_exports (): void {\n    const fns = [...fn_signatures];\n    for (const sig of fns) {\n        const wf: any = wrapped_c_functions;\n        const [lazyOrSkip, name, returnType, argTypes, opts] = sig;\n        const maybeSkip = typeof lazyOrSkip === \"function\";\n        if (lazyOrSkip === true || maybeSkip) {\n            // lazy init on first run\n            wf[name] = function (...args: any[]) {\n                const isNotSkipped = !maybeSkip || !lazyOrSkip();\n                mono_assert(isNotSkipped, () => `cwrap ${name} should not be called when binding was skipped`);\n                const fce = cwrap(name, returnType, argTypes, opts);\n                wf[name] = fce;\n                return fce(...args);","sourceCodeStart":290,"sourceCodeEnd":326,"githubUrl":"https://github.com/dotnet/runtime/blob/60108ba66eb7d1d12f595480091b4ad80a24b172/src/mono/browser/runtime/cwraps.ts#L290-L326","documentation":"Thrown by the internal `cwrap` helper in the .NET wasm runtime when it cannot resolve a C export by name. The helper first tries a fast path reading `Module.wasmExports[name]`, then falls back to emscripten's `Module.cwrap`; if neither yields a function, the runtime cannot expose the native interop binding and aborts. This almost always indicates the wasm module was stripped of an expected export or `init_c_exports` ran before the wasm module finished instantiating.","triggerScenarios":"Triggered from `init_c_exports` (or its lazy per-call wrapper at cwraps.ts:321-327) when iterating `fn_signatures` and binding each name. A name is missing because (a) the linker/emscripten dead-code-elimination removed the export, (b) the loaded `dotnet.native.wasm` is from a different build than `dotnet.runtime.js`, or (c) `Module.wasmExports` is still undefined and emscripten's lazy wrapper also returns nothing.","commonSituations":"Using a custom emscripten link step that strips exports; partial deploy where `dotnet.native.wasm` and `dotnet.runtime.js` come from different SDK builds; calling a wrapped export very early in startup before `onRuntimeInitialized`; running against an AOT/interpreter wasm build that omitted a particular native export.","solutions":["Re-deploy the matching pair of `dotnet.runtime.js` and `dotnet.native.wasm` from one publish output.","Defer any runtime API calls until after `dotnet.createDotnetRuntime` resolves (the `onRuntimeInitialized` / module.ready promise).","If you customised emscripten export flags, ensure `-s EXPORTED_FUNCTIONS` (or `EXPORT_KEEPALIVE`) includes the missing native symbol; check the name printed in the error.","Rebuild with `--verbosity detailed` and inspect the linker output to confirm the export survives."],"exampleFix":"// before: calling a binding before runtime ready\nconst r = cwraps.mono_wasm_add_assembly(...); // throws 'cwrap mono_wasm_add_assembly not found'\n\n// after: wait for the runtime module promise\nawait dotnet.createDotnetRuntime(opts);\nconst r = cwraps.mono_wasm_add_assembly(...);","handlingStrategy":"validation","validationCode":"function isExportAvailable (name) {\n  const m = Module.wasmExports || {};\n  return typeof m[name] === 'function';\n}\n// guard before use:\nif (!isExportAvailable('mono_wasm_add_assembly')) { /* await runtimeReadyPromise */ }","typeGuard":"function isWasmReady (): boolean {\n  return !!Module.wasmExports && typeof Module.cwrap === 'function';\n}","tryCatchPattern":"try {\n  return cwraps.mono_wasm_add_assembly(name, ptr, len);\n} catch (e) {\n  if (e instanceof Error && /cwrap .* not found/.test(e.message)) {\n    throw new Error(`Runtime binding missing; ensure the runtime module finished loading and that dotnet.runtime.js matches dotnet.native.wasm. Cause: ${e.message}`);\n  }\n  throw e;\n}","preventionTips":["Always `await dotnet.createDotnetRuntime(opts)` (or the module.ready promise) before touching any wrapped export.","Ship `dotnet.runtime.js` and `dotnet.native.wasm` from the same publish output.","If customising emscripten exports, keep the .NET required exports on the EXPORTED_FUNCTIONS list."],"tags":["cwraps","emscripten","wasm-exports","linker","runtime"],"backgroundTag":null,"analyzedSha":"60108ba66eb7d1d12f595480091b4ad80a24b172","analyzedAt":"2026-08-10T18:54:11.478Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}