{"record":{"id":"7c4065da42891e3f","repo":"can1357/oh-my-pi","slug":"extension-runtime-not-initialized-action-methods","errorCode":null,"errorMessage":"Extension runtime not initialized. Action methods cannot be called during extension loading.","messagePattern":"Extension runtime not initialized\\. Action methods cannot be called during extension loading\\.","errorType":"exception","errorClass":"ExtensionRuntimeNotInitializedError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/extensibility/extensions/loader.ts","lineNumber":89,"sourceCode":"/**\n * Extension runtime with throwing stubs for action methods.\n * These are replaced with real implementations during initialization.\n */\nexport class ExtensionRuntime implements IExtensionRuntime {\n\tflagValues = new Map<string, boolean | string>();\n\tpendingProviderRegistrations: Array<{ name: string; config: ProviderConfig; sourceId: string }> = [];\n\n\tregisterProvider(name: string, config: ProviderConfig, sourceId: string): void {\n\t\tthis.pendingProviderRegistrations.push({ name, config, sourceId });\n\t}\n\n\tunregisterProvider(name: string): void {\n\t\tconst remaining = this.pendingProviderRegistrations.filter(registration => registration.name !== name);\n\t\tthis.pendingProviderRegistrations.splice(0, this.pendingProviderRegistrations.length, ...remaining);\n\t}\n\n\tsendMessage(): void {\n\t\tthrow new ExtensionRuntimeNotInitializedError();\n\t}\n\n\tsendUserMessage(): void {\n\t\tthrow new ExtensionRuntimeNotInitializedError();\n\t}\n\n\tappendEntry(): void {\n\t\tthrow new ExtensionRuntimeNotInitializedError();\n\t}\n\n\tsetLabel(): void {\n\t\tthrow new ExtensionRuntimeNotInitializedError();\n\t}\n\n\tgetActiveTools(): string[] {\n\t\tthrow new ExtensionRuntimeNotInitializedError();\n\t}\n","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/extensibility/extensions/loader.ts#L71-L107","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nexport default function (pi) {\n  pi.sendMessage('hello'); // throws: runtime not initialized yet\n}\n// after\nexport default function (pi) {\n  pi.on('session_start', () => pi.sendMessage('hello'));\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  runtime.sendMessage(text);\n} catch (err) {\n  if (err instanceof ExtensionRuntimeNotInitializedError) {\n    // defer: queue the message and send from a post-init hook/event handler\n  } else throw err;\n}","preventionTips":["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"],"tags":["extensions","lifecycle","initialization-order"],"backgroundTag":"used-before-initialized","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}