ruvnet/ruflo · error · Error

Template not found: ${id}

Error message

Template not found: ${id}

What it means

Worker-side mirror of the gallery guard: createMockGallery().get(id) in wasm.worker.ts throws when builtins.find(b => b.id === id) is undefined. Same semantics as the glue-side get() but operating on the worker's own (mock) builtins list, which can diverge from src/lib/wasm/index.ts if the two are not kept in sync.

Source

Thrown at ruflo/src/ruvocal/src/lib/wasm/wasm.worker.ts:229

			description: "Web search + note-taking with persistent memory.",
			category: "knowledge",
		},
	];

	let activeId: string | null = null;

	return {
		list: () => builtins.slice(),
		listByCategory: (cat) => builtins.filter((t) => t.category === cat),
		search: (q) => {
			const needle = q.toLowerCase();
			return builtins
				.filter((t) => t.name.toLowerCase().includes(needle) || t.description.toLowerCase().includes(needle))
				.map((t, idx) => ({ ...t, relevance: 1 - idx * 0.1, tags: [] }));
		},
		get: (id) => {
			const t = builtins.find((b) => b.id === id);
			if (!t) throw new Error(`Template not found: ${id}`);
			return t;
		},
		setActive: (id) => {
			activeId = id;
		},
		getActive: () => activeId,
		count: () => builtins.length,
		getCategories: () => {
			const out: Record<string, number> = {};
			for (const t of builtins) out[t.category] = (out[t.category] ?? 0) + 1;
			return out;
		},
	};
}

async function ensureLoaded(): Promise<void> {
	if (mcpServer && gallery) return;
	if (loadPromise) return loadPromise;

View on GitHub (pinned to 6b01dc5a68)

Solutions

  1. Before posting templates.get to the worker, post templates.list and confirm membership.
  2. Keep the worker mock builtins and the glue builtinTemplates in lockstep (single source of truth where possible).
  3. On the main thread, treat a thrown "Template not found" from the worker as a signal to clear the persisted activeTemplateId.

Example fix

// before
postMessage({ id, method: "templates.get", params: { id: staleId } });
// after
const list = await postRPC(worker, "templates.list", {});
if (!list.some((t) => t.id === staleId)) return null;
const t = await postRPC(worker, "templates.get", { id: staleId });
Defensive patterns

Strategy: validation

Validate before calling

const list = await postRPC(worker, "templates.list", {});
if (!list.some((t) => t.id === id)) {
  throw new Error(`unknown template ${id} in worker gallery`);
}
return await postRPC(worker, "templates.get", { id });

Type guard

function isKnownInWorker(list: { id: string }[], id: string): boolean {
  return list.some((t) => t.id === id);
}

Try / catch

try {
  return await postRPC(worker, "templates.get", { id });
} catch (e) {
  if (String((e as Error)?.message).startsWith("Template not found")) {
    await clearActiveTemplateId();
    return null;
  }
  throw e;
}

Prevention

When it happens

Trigger: The main thread posts a { method: "templates.get", params: { id } } message to the worker for an id not in the worker's builtins array; or the worker gallery was reset and the id is stale.

Common situations: Worker and glue builtins out of sync after a partial edit; a persisted activeTemplateId from a previous version; a search() that returned a relevance-ranked list but the caller then requests an id that was filtered out.

Related errors


AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12). Data as JSON: /api/errors/9191b474fd69394b. Report an issue: GitHub.