{"record":{"id":"235b1a414b543db6","repo":"can1357/oh-my-pi","slug":"plugin-must-implement-oninvalidate","errorCode":null,"errorMessage":"Plugin must implement onInvalidate","messagePattern":"Plugin must implement onInvalidate","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/mnemopi/src/core/plugins.ts","lineNumber":46,"sourceCode":"\tinitialize(): void {\n\t\tthis.initialized = true;\n\t}\n\n\tshutdown(): void {\n\t\tthis.initialized = false;\n\t}\n\n\tonRemember(_memory: MemoryDict): void {\n\t\tthrow new TypeError(\"Plugin must implement onRemember\");\n\t}\n\tonRecall(_memory: MemoryDict): void {\n\t\tthrow new TypeError(\"Plugin must implement onRecall\");\n\t}\n\tonConsolidate(_summary: MemoryDict): void {\n\t\tthrow new TypeError(\"Plugin must implement onConsolidate\");\n\t}\n\tonInvalidate(_memoryId: string): void {\n\t\tthrow new TypeError(\"Plugin must implement onInvalidate\");\n\t}\n\ttoDict(): Record<string, unknown> {\n\t\treturn {\n\t\t\tname: this.name,\n\t\t\tversion: this.version,\n\t\t\tenabled: this.enabled,\n\t\t\tinitialized: this.initialized,\n\t\t\tconfig: this.config,\n\t\t};\n\t}\n}\n\nfunction previewContent(content: unknown, maxLen = 80): string {\n\tconst text = typeof content === \"string\" ? content : \"\";\n\tif (text.length <= maxLen) return text;\n\treturn `${text.slice(0, maxLen)}...`;\n}\n","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/mnemopi/src/core/plugins.ts#L28-L64","documentation":"MnemopiPlugin's onInvalidate is a throwing stub that subclasses must override; the host calls it when a memory id is invalidated. This TypeError means an invalidation event reached a plugin that never implemented the hook.","triggerScenarios":"A registered plugin subclass without an onInvalidate override, triggered whenever a memory is invalidated/deleted and the host calls plugin.onInvalidate(memoryId).","commonSituations":"Plugins covering only remember/recall/consolidate hooks; a copy of the plugin predating the onInvalidate hook; typos like onInvalidate(s) vs oninvalidate breaking the override.","solutions":["Override onInvalidate(memoryId: string): void in the plugin subclass","Add a no-op override if invalidation events are irrelevant to the plugin","Confirm the exact method name/casing matches onInvalidate so the override actually binds"],"exampleFix":"// before\nclass MyPlugin extends MnemopiPlugin { override onConsolidate(s: MemoryDict): void {} }\n// after\nclass MyPlugin extends MnemopiPlugin { override onConsolidate(s: MemoryDict): void {} override onInvalidate(id: string): void { /* ... */ } }","handlingStrategy":"type-guard","validationCode":"function implementsOnInvalidate(p: MnemopiPlugin): boolean {\n  return p.onInvalidate !== MnemopiPlugin.prototype.onInvalidate;\n}\nif (!implementsOnInvalidate(plugin)) throw new Error(`plugin ${plugin.name} must override onInvalidate`);","typeGuard":"function overridesOnInvalidate<P extends MnemopiPlugin>(p: P): p is P & { onInvalidate(id: string): void } {\n  return p.onInvalidate !== MnemopiPlugin.prototype.onInvalidate;\n}","tryCatchPattern":"try {\n  host.invalidate(memoryId);\n} catch (err) {\n  if (err instanceof TypeError && err.message === \"Plugin must implement onInvalidate\") {\n    logger.error(`plugin ${plugin.name} lacks onInvalidate; skipping invalidation event`);\n  } else throw err;\n}","preventionTips":["Scaffold plugins with all four hook overrides present","Verify exact method casing (onInvalidate) — near-misses silently fall through to the stub","Use `override` keyword so the compiler flags missing base-hook implementations","Add a conformance check at plugin registration time comparing against MnemopiPlugin.prototype"],"tags":["typescript","plugins","unimplemented-method"],"backgroundTag":"unimplemented-hook-method","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}