dotnet/runtime · error · Error

Invalid jsThreadBlockingMode

Error message

Invalid jsThreadBlockingMode

What it means

Thrown by install_main_synchronization_context() when the jsThreadBlockingMode argument does not match any of the four known enum values (PreventSynchronousJSExport, ThrowWhenBlockingWait, WarnWhenBlockingWait, DangerousAllowBlockingWait). The switch statement's default case fires. This is a configuration or programming error: an invalid string or number was passed where a JSThreadBlockingMode enum value is required.

Solutions

  1. Use one of the four valid JSThreadBlockingMode string values: 'PreventSynchronousJSExport', 'ThrowWhenBlockingWait', 'WarnWhenBlockingWait', or 'DangerousAllowBlockingWait'.
  2. Validate the config value before passing it: check against the known set.
  3. If loading config from JSON, verify the spelling of the jsThreadBlockingMode field.
  4. Leave jsThreadBlockingMode unset to use the default (PreventSynchronousJSExport) if you don't need a specific mode.

Example fix

// before (typo in config)
const runtime = await dotnet
  .withConfig({ config: { jsThreadBlockingMode: 'PreventSyncExport' } })
  .create();

// after (correct enum value)
const runtime = await dotnet
  .withConfig({ config: { jsThreadBlockingMode: 'PreventSynchronousJSExport' } })
  .create();
Defensive patterns

Strategy: validation

Validate before calling

// Validate jsThreadBlockingMode before passing to config
const validModes = ['PreventSynchronousJSExport', 'ThrowWhenBlockingWait', 'WarnWhenBlockingWait', 'DangerousAllowBlockingWait'];
if (config.jsThreadBlockingMode && !validModes.includes(config.jsThreadBlockingMode)) {
  throw new Error(`Invalid jsThreadBlockingMode: ${config.jsThreadBlockingMode}. Must be one of: ${validModes.join(', ')}`);
}

Type guard

function isValidJSThreadBlockingMode(mode: string): mode is 'PreventSynchronousJSExport' | 'ThrowWhenBlockingWait' | 'WarnWhenBlockingWait' | 'DangerousAllowBlockingWait' {
  return ['PreventSynchronousJSExport', 'ThrowWhenBlockingWait', 'WarnWhenBlockingWait', 'DangerousAllowBlockingWait'].includes(mode);
}

Prevention

When it happens

Trigger: Calling install_main_synchronization_context() with an unrecognized jsThreadBlockingMode value, or configuring the runtime with a misspelled or non-enum jsThreadBlockingMode string in the config. Also triggers if the config is loaded from JSON with a typo in the mode name.

Common situations: Typo in config JSON (e.g., 'PreventSyncJSExport' instead of 'PreventSynchronousJSExport'). Passing a numeric value instead of the enum string. Passing undefined or null that slips through the switch. Version mismatch where an old config uses a mode name that was renamed.

Related errors


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

Appendix: source

Thrown at src/mono/browser/runtime/managed-exports.ts:273

        const arg2 = get_arg(args, 3);
        set_arg_intptr(arg1, mono_wasm_main_thread_ptr() as any);

        // sync with JSHostImplementation.Types.cs
        switch (jsThreadBlockingMode) {
            case JSThreadBlockingMode.PreventSynchronousJSExport:
                set_arg_i32(arg2, 0);
                break;
            case JSThreadBlockingMode.ThrowWhenBlockingWait:
                set_arg_i32(arg2, 1);
                break;
            case JSThreadBlockingMode.WarnWhenBlockingWait:
                set_arg_i32(arg2, 2);
                break;
            case JSThreadBlockingMode.DangerousAllowBlockingWait:
                set_arg_i32(arg2, 100);
                break;
            default:
                throw new Error("Invalid jsThreadBlockingMode");
        }

        // this block is like invoke_sync_jsexport() but without assert_js_interop()
        cwraps.mono_wasm_invoke_jsexport(managedExports.InstallMainSynchronizationContext!, args);
        if (is_args_exception(args)) {
            const exc = get_arg(args, 0);
            throw marshal_exception_to_js(exc);
        }
        return get_arg_gc_handle(res) as any;
    } catch (e) {
        mono_log_error("install_main_synchronization_context failed", e);
        throw e;
    }
}

export function invoke_async_jsexport (managedTID: PThreadPtr, method: MonoMethod, args: JSMarshalerArguments, size: number): void {
    assert_js_interop();
    if (!WasmEnableThreads || runtimeHelpers.isManagedRunningOnCurrentThread) {

View on GitHub (pinned to 60108ba66e)