dotnet/runtime · critical · Error

Webcil asset '${virtualPath}' is missing payloadSize in the

Error message

Webcil asset '${virtualPath}' is missing payloadSize in the boot config.

What it means

Thrown by instantiateWebcilModule() (src/native/libs/Common/JavaScript/host/assets.ts:49). The host ABI expects every Webcil-in-Wasm asset to declare its payloadSize in the boot config so the loader can pre-allocate the exact image buffer without parsing the data section. When payloadSize is not a number or is 0, the loader refuses to proceed because it cannot size the allocation.

Source

Thrown at src/native/libs/Common/JavaScript/host/assets.ts:54

        }

        const ptr = _ems_.HEAPU32[ptrPtr as any >>> 2];
        _ems_.HEAPU8.set(bytes, ptr >>> 0);

        _ems_.dotnetLogger.debug(`Registered assembly '${virtualPath}' (shortName: '${shortName}') at ${ptr.toString(16)} length ${bytes.length}`);
        loadedAssemblies.set(virtualPath, { ptr, length: bytes.length });
        loadedAssemblies.set(shortName, { ptr, length: bytes.length });
    } finally {
        _ems_.stackRestore(sp);
    }
}

export async function instantiateWebcilModule(webcilPromise: Promise<Response>, memory: WebAssembly.Memory, virtualPath: string, tableSize?: number, payloadSize?: number): Promise<void> {
    // The boot config carries payloadSize for every webcil asset (and tableSize for R2R images), so
    // the loader never buffers the bytes, parses the data section or calls getWebcilSize. Assets
    // without a tableSize are plain (Webcil wrapper version 0) images.
    if (typeof payloadSize !== "number" || payloadSize === 0) {
        throw new Error(`Webcil asset '${virtualPath}' is missing payloadSize in the boot config.`);
    }
    const tableEntries = typeof tableSize === "number" ? tableSize : 0;

    const res = await checkWebcilResponse(webcilPromise, virtualPath);
    const payloadPtr = allocWebcilPayload(payloadSize);
    const imports: WebAssembly.Imports = { webcil: buildWebcilImports(memory, payloadPtr, tableEntries) };

    try {
        let instance: WebAssembly.Instance;
        const contentType = res.headers && res.headers.get ? res.headers.get("Content-Type") : undefined;
        const streamingOk = hasInstantiateStreaming && typeof globalThis.Response === "function" && res instanceof globalThis.Response && contentType === "application/wasm";
        if (streamingOk) {
            const instantiated = await WebAssembly.instantiateStreaming(res, imports);
            instance = instantiated.instance;
        } else {
            const data = await res.arrayBuffer();
            const instantiated = await WebAssembly.instantiate(data, imports);
            instance = instantiated.instance;

View on GitHub (pinned to 60108ba66e)

Solutions

  1. Re-publish the app with the same SDK/runtime version that ships the loader so the boot config emits payloadSize for every webcil asset.
  2. If a custom loadBootResourceCallback rewrites asset metadata, make sure it forwards payloadSize (and tableSize) verbatim.
  3. Verify the published blazor.boot.json / runtime config contains a numeric payloadSize for each *.wasm assembly entry.

Example fix

// before (custom loader drops payloadSize)
loadBootResource(type, name, uri) {
  return { name, url: uri }; // payloadSize lost -> 'missing payloadSize'
}

// after
loadBootResource(type, name, uri, hash, behavior, asset) {
  return { name, url: uri, payloadSize: asset.payloadSize, tableSize: asset.tableSize };
}
Defensive patterns

Strategy: validation

Validate before calling

function assertWebcilAssetsHavePayloadSize(resources: any): void {
  for (const a of resources?.assembly ?? []) {
    if (a.behavior === 'webcil' && (typeof a.payloadSize !== 'number' || a.payloadSize === 0)) {
      throw new Error(`Asset ${a.name} is missing payloadSize`);
    }
  }
}

Type guard

function isWebcilAsset(a: any): a is { payloadSize: number; tableSize?: number; virtualPath: string } {
  return a && typeof a.payloadSize === 'number' && a.payloadSize > 0;
}

Prevention

When it happens

Trigger: fetchWebcil() (loader/assets.ts:172) calls instantiateWebcilModule with assetInternal.tableSize and assetInternal.payloadSize read from the boot config. If the asset entry for a .wasm assembly lacks payloadSize (or it is 0/undefined), the guard at line 53 fires.

Common situations: Mixing a Webcil-capable runtime with an older publish output that did not emit payloadSize per asset; hand-editing or stripping the boot config; a custom loadBootResourceCallback that drops the payloadSize field when rewriting asset metadata.

Related errors


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