neoclide/coc.nvim · error
Extension ${id} not registered!
Error message
Extension ${id} not registered! What it means
activate()/activateWithSet in src/extension/manager.ts throws when the requested extension id has no entry in the ExtensionManager registry. Activation can only proceed for extensions previously loaded/registered (internal, single-file, or loaded from a folder). A missing entry is treated as a hard programming/state error rather than a soft 'not active' result.
Source
Thrown at src/extension/manager.ts:270
public get loadedExtensions(): string[] {
return Array.from(this.extensions.keys())
}
public get all(): Extension<API>[] {
return Array.from(this.extensions.values()).map(o => o.extension)
}
/**
* Activate extension, throw error if disabled or doesn't exist.
* Returns true if extension successfully activated.
*/
public async activate(id: string): Promise<boolean> {
return this.activateWithSet(id, new Set())
}
private async activateWithSet(id: string, activating: Set<string>): Promise<boolean> {
let item = this.extensions.get(id)
if (!item) throw new Error(`Extension ${id} not registered!`)
let { extension } = item
if (extension.isActive) return true
if (activating.has(id)) {
logger.warn(`Circular dependency detected: ${id}`)
return false
}
activating.add(id)
const { packageJSON } = extension
if (packageJSON.extensionDependencies?.length > 0) {
const deps = packageJSON.extensionDependencies
const results = await Promise.allSettled(deps.map(dep => this.activateWithSet(dep, activating)))
for (let i = 0; i < results.length; i++) {
const result = results[i]
if (result.status === 'rejected' || (result.status === 'fulfilled' && !result.value)) {
const dep = deps[i]
const reason = result.status === 'rejected' ? result.reason : undefined
if (reason !== undefined) {
logger.error(`Could not activate dependency ${dep} for ${id}.`, reason)View on GitHub (pinned to 50e974d969)
Solutions
- Verify the exact id: check the registered ids (e.g. via extension list / package.json `name`) and fix the caller's id string
- Ensure the extension is loaded before activating: call loadExtension/loadExtensionFile for the folder or file first
- Check whether the extension was disabled via coc.extensions configuration and re-enable it
- If activating from an event handler, guard with a registry lookup (getExtension(id)) before calling activate
Example fix
// before
await extensionManager.activate('coc-tsservers') // typo
// after
if (extensionManager.getExtension('coc-tsserver')) {
await extensionManager.activate('coc-tsserver')
} Defensive patterns
Strategy: validation
Validate before calling
if (!manager.getExtension(id)) {
logger.warn(`skip activate: ${id} not registered`)
return false
} Try / catch
try {
await manager.activate(id)
} catch (e) {
if (/not registered!?$/.test(e.message)) {
logger.warn(`extension ${id} unavailable:`, e.message)
} else throw e
} Prevention
- Copy extension ids from the extension's package.json rather than typing them
- Load extensions before referencing them in activation code
- Re-check registration after unload/disable operations
- Avoid stale references in autocmds/keybindings after removing extensions
When it happens
Trigger: Calling activate(id) (e.g. via workspace.activateExtension flow or an activation event) with an id that was never loaded, was unloaded/unregistered, or is misspelled; racing an unload that removed the map entry before activation.
Common situations: Typo in the extension id in activation events or coc-settings; extension disabled/removed but still referenced by a keybinding or language trigger; calling activate after unloadExtension; extension failed to load earlier so it was never registered.
Related errors
- Command: ${command} not found
- keymap: "${name}" already exists.
- ${this.def} has no release older than ${releaseAge} days.
- ${this.def} is not older than ${releaseAge} days.
- Extension ${id} not registered
AI-assisted analysis of neoclide/coc.nvim@50e974d969 (2026-08-31).
Data as JSON: /api/errors/727fe76f6427d854.
Report an issue: GitHub.