dotnet/runtime · error · Error

Unrecognized asset behavior

Error message

Unrecognized asset behavior:${asset.behavior}, for asset ${asset.name}

What it means

Thrown by `instantiate_asset` in the .NET WebAssembly asset loader when an asset's `behavior` field does not match any case of the dispatch switch (dotnetwasm, js-module-diagnostics, symbols, resource, assembly, pdb, heap, icu, vfs). The runtime cannot decide how to load the asset, so it errors rather than silently skipping it. This is a configuration/contract error in the asset manifest produced by the .NET WASI/browser build.

Solutions

  1. Inspect `config.assets` at runtime (log `runtimeHelpers.config.assets`) and find the entry whose `behavior` is not in {dotnetwasm, js-module-diagnostics, symbols, resource, assembly, pdb, heap, icu, vfs}.
  2. Re-generate the assets config by re-running the .NET wasm publish step with the runtime that is actually loaded.
  3. Remove or correct any hand-added asset entries with an unsupported behavior.
  4. If a genuinely new behavior is required, extend the switch in assets.ts:25 to handle it.

Example fix

// before: typo'd behavior in the config
config.assets = [{ name: 'MyLib.dll', behavior: 'asembly' }]; // throws

// after: use a supported behavior literal
config.assets = [{ name: 'MyLib.dll', behavior: 'assembly' }];
Defensive patterns

Strategy: validation

Validate before calling

const KNOWN_BEHAVIORS = new Set(['dotnetwasm','js-module-diagnostics','symbols','resource','assembly','pdb','heap','icu','vfs']);
function validateAssets (assets) {
  return assets.filter(a => !KNOWN_BEHAVIORS.has(a.behavior));
}
const bad = validateAssets(runtimeHelpers.config.assets || []); if (bad.length) console.error('bad assets', bad);

Type guard

type AssetBehavior = 'dotnetwasm'|'js-module-diagnostics'|'symbols'|'resource'|'assembly'|'pdb'|'heap'|'icu'|'vfs';
function isAssetBehavior (v: unknown): v is AssetBehavior {
  return typeof v === 'string' && ['dotnetwasm','js-module-diagnostics','symbols','resource','assembly','pdb','heap','icu','vfs'].includes(v);
}

Prevention

When it happens

Trigger: The runtime iterates `runtimeHelpers.config.assets` and calls `instantiate_asset(asset, url, bytes)`. If `asset.behavior` is undefined, null, a typo, or a value produced by a newer SDK that this runtime build does not understand, execution falls to the `default:` branch at src/mono/browser/runtime/assets.ts:60-61. Custom asset entries injected through `assets` config that don't use one of the enumerated behaviors also trip it.

Common situations: Hand-editing the `assets` JSON in the runtime config and misspelling a behavior; mixing a runtime bundle with a `dotnet.runtime.js` from a different SDK that emits behaviors this loader doesn't know; downgrading the runtime bundle while keeping a config generated by a newer SDK.

Related errors


AI-assisted analysis of dotnet/runtime@60108ba66e (2026-08-10). Data as JSON: /api/errors/e62f4a331edeeabf. Report an issue: GitHub.

Appendix: source

Thrown at src/mono/browser/runtime/assets.ts:61

            const lastSlash = virtualName.lastIndexOf("/");
            let parentDirectory = (lastSlash > 0)
                ? virtualName.substring(0, lastSlash)
                : browserVirtualAppBase;
            let fileName = (lastSlash > 0)
                ? virtualName.substring(lastSlash + 1)
                : virtualName;
            if (fileName.startsWith("/"))
                fileName = fileName.substring(1);
            if (!parentDirectory.startsWith("/"))
                parentDirectory = browserVirtualAppBase + parentDirectory;

            mono_log_debug(() => `Creating file '${fileName}' in directory '${parentDirectory}'`);
            Module.FS_createPath("/", parentDirectory, true, true);
            Module.FS_createDataFile(parentDirectory, fileName, bytes, true /* canRead */, true /* canWrite */, true /* canOwn */);
            break;
        }
        default:
            throw new Error(`Unrecognized asset behavior:${asset.behavior}, for asset ${asset.name}`);
    }

    if (asset.behavior === "assembly") {
        // this is reading flag inside the DLL about the existence of PDB
        // it doesn't relate to whether the .pdb file is downloaded at all
        const hasPdb = cwraps.mono_wasm_add_assembly(virtualName, offset!, bytes.length);

        if (!hasPdb) {
            const index = loaderHelpers._loaded_files.findIndex(element => element.file == virtualName);
            loaderHelpers._loaded_files.splice(index, 1);
        }
    } else if (asset.behavior === "pdb") {
        cwraps.mono_wasm_add_assembly(virtualName, offset!, bytes.length);
    } else if (asset.behavior === "icu") {
        wasm_load_icu_data(offset!);
    } else if (asset.behavior === "resource") {
        cwraps.mono_wasm_add_satellite_assembly(virtualName, asset.culture || "", offset!, bytes.length);
    }

View on GitHub (pinned to 60108ba66e)