Stream: jco

Topic: [browser] poll_oneoff - Not a valid "Pollable"


view this post on Zulip Ed (Oct 30 2025 at 01:31):

Ed said:

TLDR: when my component calls WASI poll_oneoff it fails with "Not a valid 'Pollable' resource"

This is a real hack, but I hope I can be pointed in the right direction as I can't find any resources for more info on this. Background: this project is to perform patching on binary firmware files for industrial equipment. We have a working prototype via a container and need to get it out to the front line

We use Container2WASM (https://github.com/container2wasm/container2wasm) to build the container into a WASM module (which uses WASI Preview1), then call wasm-tools to make that into a component (using the wasm1 console adapter) and then call JCO to transpile that.

The core loads and starts, but once the VM starts polling, it fails witht he following exception:

[PatchFirmware] Error: TypeError: Resource error: Not a valid "Pollable" resource.

at trampoline6 (firmwarepatcher.js:862:11)

at poll_oneoff (firmwarepatcher.core2.wasm:0x54a6)

at abba7226:0x2b0

at __imported_wasi_snapshot_preview1_poll_oneoff (firmwarepatcher.core.wasm:0xae85)

at __wasi_poll_oneoff (firmwarepatcher.core.wasm:0x70787)

at pselect (firmwarepatcher.core.wasm:0x6be92)

at select (firmwarepatcher.core.wasm:0x6c045)

at virt_machine_run (firmwarepatcher.core.wasm:0x9693)

at main (firmwarepatcher.core.wasm:0xabc5)

at __main_void (firmwarepatcher.core.wasm:0x6c4dc)

Previously we were using browser_wasi_shim with C2W (https://github.com/bjorn3/browser_wasi_shim) which handled the polls correctly. We switched as that package lacks full WASI support, unlike JCO which we have successfully used for other (less janky) projects. But we haven't used it for command/CLI before, and wonder if we are missing a stdin/stdout which is causing the issue?

We are working on a proper solution... I promise! But for now, we need to get this working, so any advice would be great.

Here is the full build process:

docker build -t dk-patcher:latest --platform=linux/riscv64 .
c2w --target-arch=riscv64 -- dk-patcher:latest ./temptopatch.wasm
wasm-tools component new ./temptopatch.wasm --adapt wasi_snapshot_preview1=adapter.wasm -o temp.component.wasm
bunx @bytecodealliance/jco transpile ./temp.component.wasm -o ../webserver/src/lib/patcher --name 'dashkeepfirmwarepatcher' --no-namespaced-exports --async-mode jspi

Basic launch code:

import { expose } from "comlink";
import { instantiate } from "$lib/patcher/firmwarepatcher";
import {
  WASIShim,
  type WASIImportObject,
  type VersionedWASIImportObject,
} from "@bytecodealliance/preview2-shim/instantiation";

const wasmModules = import.meta.glob("$lib/patcher/*.wasm", {
  as: "url",
});

export type TPatchFirmware = typeof PatchFirmware;

async function PatchFirmware(
  firmwareBuff: ArrayBuffer,
  onStdout?: (text: string) => void,
) {
  try {
    console.log("[PatchFirmware] Starting firmware patching process");

    async function loader(path: string) {
      return await WebAssembly.compileStreaming(
        fetch(await wasmModules[`/src/lib/patcher/${path}`]()),
      );
    }

    const shimCore = new WASIShim();
    // for importing directly, i.e. wasi:cli/blah
    const shim = shimCore.getImportObject();
    // For importing when a version is defined, i.e. wasi:cli/blah@0.2.6
    const shimVersioned: VersionedWASIImportObject<"0.2.6"> =
      shimCore.getImportObject({ asVersion: "0.2.6" });
    shim satisfies WASIImportObject;
    shim satisfies VersionedWASIImportObject<"">;
    shimVersioned satisfies VersionedWASIImportObject<"0.2.6">;

    // @ts-ignore - We have provided it everything it needs (except for debug provisions)
    const instance = await instantiate(loader, {
      ...shim,
      ...shimVersioned,
    });

    const result = instance.run.run();

    console.log(result);

    return {
      success: true,
      message: "Firmware patched successfully",
      result,
    };
  } catch (error) {
    console.error("[PatchFirmware] Error:", error);
    throw error;
  }
}

expose(PatchFirmware);


Last updated: Dec 06 2025 at 06:05 UTC