dotnet/runtime · error · Error

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

Error message

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

What it means

Thrown by instantiate_asset() in assets.ts when an asset's `behavior` field does not match any of the cases handled by the switch: dotnetwasm, js-module-diagnostics, symbols, resource, assembly, pdb, heap, icu, vfs. The .NET WASM runtime boot config (dotnet.boot.js / mono-config.json) describes each downloadable asset with a behavior that tells the loader how to materialize it; an unrecognized value means the loader cannot decide what to do with the bytes and aborts. JS-module behaviors (js-module-dotnet/runtime/native/library-initializer, manifest) are intentionally handled elsewhere, so reaching this default case is a real mismatch, not a normal path.

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 290d5ab72c)

Solutions

  1. Inspect the full error message: the literal behavior value and asset name tell you exactly which entry is wrong.
  2. Regenerate the boot config: run `dotnet publish` (or your WASM build target) with the SAME SDK/runtime version as the runtime JS being served, so WasmAppBuilder emits only behaviors this runtime understands.
  3. Clear the browser cache and any CDN/ServiceWorker cache of dotnet.boot.js and the framework files so a stale manifest is not served against fresh runtime JS.
  4. If using a custom loadBootResource callback, verify you return Response/Promise for the right `behavior` and do not mutate `behavior` to an unsupported value; map unknown behaviors to null to use default loading.
  5. If you hand-edited mono-config.json, restore it from the build output and apply only documented overrides.

Example fix

// before: boot config / custom asset with a typo
{ "name": "MyLib.dll", "behavior": "asembly" }  // typo -> default case throws

// after: regenerate or correct to a known behavior
{ "name": "MyLib.dll", "behavior": "assembly" }
Defensive patterns

Strategy: validation

Validate before calling

import type { AssetBehaviors } from "./types";
const KNOWN: ReadonlySet<string> = new Set([
  "dotnetwasm", "js-module-diagnostics", "symbols", "resource",
  "assembly", "pdb", "heap", "icu", "vfs",
  "js-module-dotnet", "js-module-runtime", "js-module-native",
  "js-module-library-initializer", "manifest",
]);
function assertAssetBehavior(asset: { behavior: string; name: string }) {
  if (!KNOWN.has(asset.behavior)) {
    throw new Error(`Unsupported asset behavior '${asset.behavior}' for '${asset.name}'; regenerate boot config with matching SDK.`);
  }
}

Type guard

function isKnownAssetBehavior(b: unknown): b is AssetBehaviors {
  return typeof b === "string" && KNOWN.has(b);
}

Try / catch

try { instantiate_asset(asset, url, bytes); }
catch (e) { /* startup blocker: log asset.behavior + name, halt boot with a clear config-mismatch message */ throw e; }

Prevention

When it happens

Trigger: Calling instantiate_asset() with an AssetEntry whose `behavior` is a typo, an unknown string, undefined/null, or a behavior that belongs to a newer/older runtime than the loaded JS. Hand-editing mono-config.json or a custom loadBootResource callback that fabricates asset entries with wrong behavior values. Mixing a boot config generated by one WasmAppBuilder version with runtime JS from another.

Common situations: Upgrading the .NET SDK without rebuilding the WASM app (boot config references a behavior the old/new runtime JS disagrees on). Manually editing the generated dotnet.boot.js or its embedded mono-config. A custom CDN proxy that rewrites asset metadata. Downgrading runtime JS while keeping a newer boot manifest.

Related errors


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