DIYgod/RSSHub · error

WASM function not available

Error message

WASM function not available

What it means

Generic Error thrown by the manga-update route when the WebAssembly module fails to expose the expected genReqSign function after instantiation. The route downloads a .wasm binary from Bilibili's CDN, instantiates it via Go's WASM runtime, and checks globalThis.genReqSign. If the WASM module is corrupted, the URL is stale, or the runtime doesn't support the module, the function is undefined.

Source

Thrown at lib/routes/bilibili/manga-update.ts:47

async function genReqSign(query, body) {
    // Don't import on top-level to avoid a cyclic dependency - wasm-exec.js generated via `pnpm build`, which in turn needs wasm-exec.js to import routes correctly
    const { Go } = await import('./wasm-exec');

    // Cache the wasm binary as it's quite large (~2MB)
    // Here the binary is saved as base64 as the cache stores strings
    const wasmBufferBase64 = await cache.tryGet('bilibili-manga-wasm-20250208', async () => {
        const wasmResp = await got('https://s1.hdslb.com/bfs/manga-static/manga-pc/6732b1bf426cfc634293.wasm', {
            responseType: 'arrayBuffer',
        });
        return Buffer.from(wasmResp.data).toString('base64');
    });
    const wasmBuffer = Buffer.from(wasmBufferBase64, 'base64');

    const go = new Go();
    const { instance } = await WebAssembly.instantiate(wasmBuffer, go.importObject);
    go.run(instance);
    if (void 0 === globalThis.genReqSign) {
        throw new Error('WASM function not available');
    }

    const signature = globalThis.genReqSign(query, body, Date.now());

    return signature.sign;
}

async function handler(ctx) {
    const comic_id = ctx.req.param('comicid').startsWith('mc') ? ctx.req.param('comicid').replace('mc', '') : ctx.req.param('comicid');
    const link = `https://manga.bilibili.com/detail/mc${comic_id}`;

    const spi_response = await got('https://api.bilibili.com/x/frontend/finger/spi');

    const query = 'device=pc&platform=web&nov=25';
    const body = JSON.stringify({
        comic_id: Number(comic_id),
    });

View on GitHub (pinned to bed535e087)

Solutions

  1. Clear the cached WASM: flush/clear the Redis or in-memory cache entry 'bilibili-manga-wasm-20250208' so it re-downloads.
  2. Check if the hardcoded WASM URL (https://s1.hdslb.com/bfs/manga-static/manga-pc/6732b1bf426cfc634293.wasm) still resolves — if Bilibili changed it, update the URL and cache key in the source.
  3. Verify the downloaded buffer is actually WASM (starts with magic bytes 0x00 0x61 0x73 0x6d) and not an HTML error page.
  4. Ensure the Node.js version supports the WASM module (use Node 18+).

Example fix

// before: hardcoded URL and cache key that may go stale
const wasmResp = await got('https://s1.hdslb.com/bfs/manga-static/manga-pc/6732b1bf426cfc634293.wasm', {...});

// after: validate the buffer is real WASM before instantiating
const wasmBuffer = Buffer.from(wasmResp.data);
if (wasmBuffer.length < 8 || wasmBuffer[0] !== 0x00 || wasmBuffer[1] !== 0x61) {
    throw new Error('Downloaded WASM is invalid (got non-WASM content). URL may be stale.');
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate the WASM buffer before relying on it
const wasmBuffer = Buffer.from(wasmBufferBase64, 'base64');
const WASM_MAGIC = [0x00, 0x61, 0x73, 0x6d];
const isValidWasm = wasmBuffer.length >= 4 &&
    WASM_MAGIC.every((byte, i) => wasmBuffer[i] === byte);
if (!isValidWasm) {
    throw new Error('Invalid WASM buffer — URL may be stale or CDN returned an error page');
}

Type guard

function isValidWasmBuffer(buf: Buffer): boolean {
    return buf.length >= 4 &&
        buf[0] === 0x00 && buf[1] === 0x61 &&
        buf[2] === 0x73 && buf[3] === 0x6d;
}

function isGenReqSignAvailable(): boolean {
    return typeof globalThis.genReqSign === 'function';
}

Try / catch

try {
    const { instance } = await WebAssembly.instantiate(wasmBuffer, go.importObject);
    go.run(instance);
    if (typeof globalThis.genReqSign !== 'function') {
        throw new Error('WASM instantiated but genReqSign not found — binary may be stale');
    }
} catch (e) {
    logger.error(`WASM init failed: ${e.message}. Clearing cache.`);
    await cache.delete?.('bilibili-manga-wasm-20250208');
    throw e;
}

Prevention

When it happens

Trigger: WebAssembly.instantiate succeeds (or partially succeeds) but go.run(instance) does not register genReqSign on globalThis. Causes: the cached WASM buffer (key 'bilibili-manga-wasm-20250208') is stale/corrupted, the CDN URL returns an HTML error page instead of WASM, the Go WASM runtime version is incompatible, or Node.js lacks full WebAssembly support.

Common situations: Bilibili updated the WASM file (new hash/URL) but the cache key still holds the old binary; the CDN URL in the source is hardcoded and Bilibili moved the file; network proxy returned an error page that was cached as the WASM; Node.js version too old for the WASM features used.

Related errors


AI-assisted analysis of DIYgod/RSSHub@bed535e087 (2026-08-12). Data as JSON: /api/errors/01776faab0607071. Report an issue: GitHub.