can1357/oh-my-pi · error · ExtensionRuntimeNotInitializedError
Extension runtime not initialized. Action methods cannot be
Error message
Extension runtime not initialized. Action methods cannot be called during extension loading.
What it means
ExtensionRuntime starts with throwing stubs for all action methods; the real implementations are swapped in only after the extension loading/initialization phase completes. Calling sendMessage() on the runtime before initialization (i.e. from code that captured the runtime during extension load) throws this error to make premature use loud and explicit.
Source
Thrown at packages/coding-agent/src/extensibility/extensions/loader.ts:89
/**
* Extension runtime with throwing stubs for action methods.
* These are replaced with real implementations during initialization.
*/
export class ExtensionRuntime implements IExtensionRuntime {
flagValues = new Map<string, boolean | string>();
pendingProviderRegistrations: Array<{ name: string; config: ProviderConfig; sourceId: string }> = [];
registerProvider(name: string, config: ProviderConfig, sourceId: string): void {
this.pendingProviderRegistrations.push({ name, config, sourceId });
}
unregisterProvider(name: string): void {
const remaining = this.pendingProviderRegistrations.filter(registration => registration.name !== name);
this.pendingProviderRegistrations.splice(0, this.pendingProviderRegistrations.length, ...remaining);
}
sendMessage(): void {
throw new ExtensionRuntimeNotInitializedError();
}
sendUserMessage(): void {
throw new ExtensionRuntimeNotInitializedError();
}
appendEntry(): void {
throw new ExtensionRuntimeNotInitializedError();
}
setLabel(): void {
throw new ExtensionRuntimeNotInitializedError();
}
getActiveTools(): string[] {
throw new ExtensionRuntimeNotInitializedError();
}
View on GitHub (pinned to 9690622007)
Solutions
- Move the sendMessage call into an event handler / lifecycle callback that runs after initialization (e.g. on session start, on command), not at module or factory top level.
- Defer via the extension's init/ready hook so the real implementation is installed first.
- Verify extension initialization completed (no earlier load errors); if init failed, fix that first.
- If you must fire-and-forget, await runtime readiness before calling.
Example fix
// before
export default function (pi) {
pi.sendMessage('hello'); // throws: runtime not initialized yet
}
// after
export default function (pi) {
pi.on('session_start', () => pi.sendMessage('hello'));
} Defensive patterns
Strategy: try-catch
Try / catch
try {
runtime.sendMessage(text);
} catch (err) {
if (err instanceof ExtensionRuntimeNotInitializedError) {
// defer: queue the message and send from a post-init hook/event handler
} else throw err;
} Prevention
- Never call runtime action methods at module top level or inside the extension factory body
- Use extension lifecycle/event hooks that run after initialization
- Await a readiness signal before invoking action methods
- Check extension init logs so failures that leave stubs in place are caught early
When it happens
Trigger: An extension's factory or a module-level/top-level hook calls runtime.sendMessage() while extensions are still loading, before the runtime stubs are replaced with the connected implementations.
Common situations: Extension sends a message eagerly at import/factory time instead of inside a handler or on an event; an extension captured the runtime reference and invokes it asynchronously before init finished; initialization failed silently so stubs were never replaced.
Related errors
- DAP adapter ${this.adapter.name} is not running
- Debug session ${root.id} is still active. Terminate it befor
- Cannot ${action} on a disposed JS runtime
- Cannot set cwd on a disposed JS runtime
- ${this.#options.languageName} kernel is not running
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/7c4065da42891e3f.
Report an issue: GitHub.