can1357/oh-my-pi · error · TypeError

Plugin must implement onRecall

Error message

Plugin must implement onRecall

What it means

MnemopiPlugin's onRecall is a throwing stub: subclasses must override it because the plugin host invokes it on every memory recall. Hitting this TypeError means the registered plugin never implemented the recall hook.

Source

Thrown at packages/mnemopi/src/core/plugins.ts:40

		this.name =
			(ctor.prototype.name as string | undefined) ?? (ctor as unknown as { name?: string }).name ?? this.name;
		this.version = (ctor.prototype.version as string | undefined) ?? this.version;
		this.enabled = (ctor.prototype.enabled as boolean | undefined) ?? this.enabled;
	}

	initialize(): void {
		this.initialized = true;
	}

	shutdown(): void {
		this.initialized = false;
	}

	onRemember(_memory: MemoryDict): void {
		throw new TypeError("Plugin must implement onRemember");
	}
	onRecall(_memory: MemoryDict): void {
		throw new TypeError("Plugin must implement onRecall");
	}
	onConsolidate(_summary: MemoryDict): void {
		throw new TypeError("Plugin must implement onConsolidate");
	}
	onInvalidate(_memoryId: string): void {
		throw new TypeError("Plugin must implement onInvalidate");
	}
	toDict(): Record<string, unknown> {
		return {
			name: this.name,
			version: this.version,
			enabled: this.enabled,
			initialized: this.initialized,
			config: this.config,
		};
	}
}

View on GitHub (pinned to 9690622007)

Solutions

  1. Override onRecall(memory: MemoryDict): void in the plugin subclass
  2. Provide a no-op override if recall events are irrelevant
  3. Rebuild/redeploy the plugin so the override is actually present at runtime

Example fix

// before
class MyPlugin extends MnemopiPlugin { override onRemember(m: MemoryDict): void {} }
// after
class MyPlugin extends MnemopiPlugin { override onRemember(m: MemoryDict): void {} override onRecall(m: MemoryDict): void { /* ... */ } }
Defensive patterns

Strategy: type-guard

Validate before calling

function implementsOnRecall(p: MnemopiPlugin): boolean {
  return p.onRecall !== MnemopiPlugin.prototype.onRecall;
}
if (!implementsOnRecall(plugin)) throw new Error(`plugin ${plugin.name} must override onRecall`);

Type guard

function overridesOnRecall<P extends MnemopiPlugin>(p: P): p is P & { onRecall(m: MemoryDict): void } {
  return p.onRecall !== MnemopiPlugin.prototype.onRecall;
}

Try / catch

try {
  host.recall(id);
} catch (err) {
  if (err instanceof TypeError && err.message === "Plugin must implement onRecall") {
    logger.error(`plugin ${plugin.name} lacks onRecall; unregistering it`);
    host.unregister(plugin);
  } else throw err;
}

Prevention

When it happens

Trigger: A plugin subclass registered with the host that does not override onRecall, triggered when a memory is recalled and the host iterates plugins calling plugin.onRecall(memory).

Common situations: Writing a plugin that only cares about onRemember/onConsolidate; a refactor renaming the method so the override no longer matches; loading a stale or minified plugin build without the override.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/f442edb5e35386e3. Report an issue: GitHub.