{"record":{"id":"9191b474fd69394b","repo":"ruvnet/ruflo","slug":"template-not-found-id-9191b4","errorCode":null,"errorMessage":"Template not found: ${id}","messagePattern":"Template not found: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"ruflo/src/ruvocal/src/lib/wasm/wasm.worker.ts","lineNumber":229,"sourceCode":"\t\t\tdescription: \"Web search + note-taking with persistent memory.\",\n\t\t\tcategory: \"knowledge\",\n\t\t},\n\t];\n\n\tlet activeId: string | null = null;\n\n\treturn {\n\t\tlist: () => builtins.slice(),\n\t\tlistByCategory: (cat) => builtins.filter((t) => t.category === cat),\n\t\tsearch: (q) => {\n\t\t\tconst needle = q.toLowerCase();\n\t\t\treturn builtins\n\t\t\t\t.filter((t) => t.name.toLowerCase().includes(needle) || t.description.toLowerCase().includes(needle))\n\t\t\t\t.map((t, idx) => ({ ...t, relevance: 1 - idx * 0.1, tags: [] }));\n\t\t},\n\t\tget: (id) => {\n\t\t\tconst t = builtins.find((b) => b.id === id);\n\t\t\tif (!t) throw new Error(`Template not found: ${id}`);\n\t\t\treturn t;\n\t\t},\n\t\tsetActive: (id) => {\n\t\t\tactiveId = id;\n\t\t},\n\t\tgetActive: () => activeId,\n\t\tcount: () => builtins.length,\n\t\tgetCategories: () => {\n\t\t\tconst out: Record<string, number> = {};\n\t\t\tfor (const t of builtins) out[t.category] = (out[t.category] ?? 0) + 1;\n\t\t\treturn out;\n\t\t},\n\t};\n}\n\nasync function ensureLoaded(): Promise<void> {\n\tif (mcpServer && gallery) return;\n\tif (loadPromise) return loadPromise;","sourceCodeStart":211,"sourceCodeEnd":247,"githubUrl":"https://github.com/ruvnet/ruflo/blob/6b01dc5a687b26b3e218f796de45ec51f8fa9e8c/ruflo/src/ruvocal/src/lib/wasm/wasm.worker.ts#L211-L247","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Before posting templates.get to the worker, post templates.list and confirm membership.","Keep the worker mock builtins and the glue builtinTemplates in lockstep (single source of truth where possible).","On the main thread, treat a thrown \"Template not found\" from the worker as a signal to clear the persisted activeTemplateId."],"exampleFix":"// before\npostMessage({ id, method: \"templates.get\", params: { id: staleId } });\n// after\nconst list = await postRPC(worker, \"templates.list\", {});\nif (!list.some((t) => t.id === staleId)) return null;\nconst t = await postRPC(worker, \"templates.get\", { id: staleId });","handlingStrategy":"validation","validationCode":"const list = await postRPC(worker, \"templates.list\", {});\nif (!list.some((t) => t.id === id)) {\n  throw new Error(`unknown template ${id} in worker gallery`);\n}\nreturn await postRPC(worker, \"templates.get\", { id });","typeGuard":"function isKnownInWorker(list: { id: string }[], id: string): boolean {\n  return list.some((t) => t.id === id);\n}","tryCatchPattern":"try {\n  return await postRPC(worker, \"templates.get\", { id });\n} catch (e) {\n  if (String((e as Error)?.message).startsWith(\"Template not found\")) {\n    await clearActiveTemplateId();\n    return null;\n  }\n  throw e;\n}","preventionTips":["Keep worker mock builtins and glue builtinTemplates in lockstep (single source of truth).","Always precede templates.get with a templates.list membership check.","Treat a worker 'Template not found' as a signal to clear the persisted activeTemplateId."],"tags":["wasm","worker","template","gallery","validation"],"backgroundTag":null,"analyzedSha":"6b01dc5a687b26b3e218f796de45ec51f8fa9e8c","analyzedAt":"2026-08-12T13:20:50.148Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}