{"record":{"id":"64e86a069e6fe68b","repo":"neoclide/coc.nvim","slug":"extension-id-not-registered-64e86a","errorCode":null,"errorMessage":"Extension ${id} not registered","messagePattern":"Extension (.+?) not registered","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/extension/manager.ts","lineNumber":349,"sourceCode":"  }\n\n  /**\n   * Deactivate & unregist extension\n   */\n  public async unloadExtension(id: string): Promise<void> {\n    let item = this.extensions.get(id)\n    if (item) {\n      await this.deactivate(id)\n      this.extensions.delete(id)\n      this._onDidUnloadExtension.fire(id)\n    }\n    disposeExtension(id)\n  }\n\n  public async reloadExtension(id: string): Promise<void> {\n    let item = this.extensions.get(id)\n    if (!item || item.type == ExtensionType.Internal) {\n      throw new Error(`Extension ${id} not registered`)\n    }\n    if (item.type == ExtensionType.SingleFile) {\n      await this.loadExtensionFile(item.filepath)\n    } else {\n      await this.loadExtension(item.directory)\n    }\n  }\n\n  public async call(id: string, method: string, args: any[]): Promise<any> {\n    let item = this.extensions.get(id)\n    if (!item) throw new Error(`extension ${id} not registered`)\n    let { extension } = item\n    if (!extension.isActive) {\n      await this.activate(id)\n    }\n    let { exports } = extension\n    if (!exports || typeof exports[method] !== 'function') {\n      throw new Error(`method ${method} not found on extension ${id}`)","sourceCodeStart":331,"sourceCodeEnd":367,"githubUrl":"https://github.com/neoclide/coc.nvim/blob/50e974d9692461a69147d5cab146a8d3e439abe4/src/extension/manager.ts#L331-L367","documentation":"reloadExtension in src/extension/manager.ts throws `Extension <id> not registered` when there is no registry entry for the id, or when the entry is an Internal extension. Internal (built-in) extensions cannot be reloaded from disk, and an unknown id has nothing to reload, so both cases are rejected up front.","triggerScenarios":"watchExtension's file/watchman callback firing reloadExtension(id) after the extension was unregistered or unloaded; calling reloadExtension directly with an unknown id or with an internal extension's id.","commonSituations":"Editing a watched extension file after the extension was disabled/removed, so the watcher fires on a stale id; attempting to hot-reload a built-in internal extension; typo in the id.","solutions":["Confirm the id is registered (getExtension(id) !== undefined) and not internal before reloading","If the extension was unloaded intentionally, ignore or dispose the stale watcher instead of reloading","Reload via the correct path: loadExtension(directory) for folder extensions or loadExtensionFile for single-file ones","For internal extensions, restart the coc server instead of hot-reloading"],"exampleFix":"// before\nawait manager.reloadExtension(id) // id may be stale/internal\n// after\nconst item = manager.getExtension(id)\nif (item && item.type !== ExtensionType.Internal) await manager.reloadExtension(id)","handlingStrategy":"validation","validationCode":"const item = manager.getExtension(id)\nif (!item || item.type === 'Internal') return // cannot reload","typeGuard":null,"tryCatchPattern":"try {\n  await manager.reloadExtension(id)\n} catch (e) {\n  if (/not registered$/.test(e.message)) {\n    logger.warn(`cannot reload ${id}: not reloadable`)\n  } else throw e\n}","preventionTips":["Dispose watchers when an extension is unloaded or disabled","Never attempt to hot-reload internal extensions — restart the server instead","Verify registration and type before reload calls","Guard file-watch callbacks against stale ids"],"tags":["extension-reload","watcher","lifecycle"],"backgroundTag":"extension-not-registered","analyzedSha":"50e974d9692461a69147d5cab146a8d3e439abe4","analyzedAt":"2026-08-31T11:17:23.966Z","schemaVersion":2},"datasetVersion":"2026-09-01T08:17:40.651Z"}