ruvnet/ruflo · error · Error
WASM agent not found: ${agentId}
Error message
WASM agent not found: ${agentId} What it means
Thrown by promptWasmAgent(agentId, input) when agents.get(agentId) returns undefined — the agentId is not in the in-memory agent registry. The registry is a module-level Map keyed by IDs like 'wasm-agent-3-lkjx8', so an unknown ID means the agent was never created in this process, was already terminated, or the process restarted (the Map is not persisted).
Source
Thrown at v3/@claude-flow/cli/src/ruvector/agent-wasm.ts:195
}
/**
* Send a prompt to a WASM agent.
*
* ADR-129 P1: JsModelProvider is now wired at creation time so the WASM
* agent's internal conversation loop (multi-turn state, turn_count,
* stop conditions) runs against a real LLM. The echo-stub detection
* block is kept as a fallback for keyless environments (CI, sandboxed
* test runners) — behaviour is identical to the pre-P1 path when no
* provider key is set.
*
* Billing note: every wasm_agent_prompt call with a provider key
* configured makes a billable LLM call. Use a keyless environment to
* get the echo stub for cost-free sandboxing.
*/
export async function promptWasmAgent(agentId: string, input: string): Promise<string> {
const entry = agents.get(agentId);
if (!entry) throw new Error(`WASM agent not found: ${agentId}`);
entry.info.state = 'running';
try {
const wasmResult = await entry.agent.prompt(input);
entry.info.state = 'idle';
syncAgentInfo(entry);
// Detect the WASM echo stub (present when no JsModelProvider was
// attached, i.e. keyless environments).
const isEchoStub = typeof wasmResult === 'string' &&
(wasmResult === `echo: ${input}` || /^echo: /.test(wasmResult.slice(0, 12)));
if (!isEchoStub) {
// JsModelProvider routed through the v3 provider system — return
// the real response. turn_count was already incremented by the
// WASM runtime.
return wasmResult;
}View on GitHub (pinned to 6b01dc5a68)
Solutions
- Call listWasmAgents() before prompting to confirm the ID is still live in this process.
- If you need agent continuity across process restarts, use exportWasmState() to save and rehydrate — but note the underlying WasmAgent handle itself is not serializable; you must re-create.
- Treat the ID as ephemeral: create, use, and terminate within a single process lifetime.
- Check for a stray terminateWasmAgent call (including in error-handling paths) that removes the agent before the prompt.
Example fix
// before — assumes ID is still valid
const out = await promptWasmAgent(staleId, input);
// after — verify liveness, recreate if gone
const live = listWasmAgents().some(a => a.id === staleId);
if (!live) {
const info = await createWasmAgent(config);
return promptWasmAgent(info.id, input);
}
return promptWasmAgent(staleId, input); Defensive patterns
Strategy: type-guard
Validate before calling
import { listWasmAgents, getWasmAgent } from './agent-wasm';
function assertAgentLive(agentId: string): void {
if (!getWasmAgent(agentId)) {
throw new Error(
`agent ${agentId} not live. Active: ${listWasmAgents().map(a => a.id).join(', ') || '(none)'}`
);
}
}
assertAgentLive(agentId);
const out = await promptWasmAgent(agentId, input); Type guard
function isLiveAgentId(id: string): boolean {
return getWasmAgent(id) !== null;
} Try / catch
try {
return await promptWasmAgent(agentId, input);
} catch (e) {
if (/WASM agent not found/.test(String(e))) {
// Recreate and retry once — agent IDs are ephemeral.
const info = await createWasmAgent(config);
return promptWasmAgent(info.id, input);
}
throw e;
} Prevention
- Treat agent IDs as ephemeral — valid only within the process that created them.
- Snap listWasmAgents() before batch operations rather than probing stale IDs.
- Serialize terminateWasmAgent with readers to avoid freeing an agent mid-prompt.
- For long-lived services, design clients to recover from 'agent not found' by recreating.
When it happens
Trigger: Calling promptWasmAgent with an ID returned from a previous process run (after restart); passing an ID from listWasmAgents() after terminateWasmAgent was called on it; typo or copy-paste error in the agentId string; holding an ID across an await that outlived a terminate call elsewhere; using an ID from a different worker thread (the Map is per-process).
Common situations: Long-running server that creates an agent, restarts (deploy/restart), and a client retries with the old ID; CLI command creates an agent in one invocation and tries to prompt it in the next (separate processes); concurrent code path calls terminateWasmAgent while another caller still holds the ID; ID was persisted to disk via exportWasmState and reloaded, but the in-memory agent was not.
Related errors
- Gallery template not found: ${templateId}
- Failed to load WASM module
- MCP initialization failed: ${initResponse.error.message}
- Template not found: ${id}
- Template not found: ${id}
AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12).
Data as JSON: /api/errors/a46f397d9c9ab3af.
Report an issue: GitHub.