neoclide/coc.nvim · error

extension ${id} not registered

Error message

extension ${id} not registered

What it means

ExtensionManager.call(id, method, args) performs remote-style invocation of an exported function on an extension. It throws `extension <id> not registered` when no extension with that id exists in the manager. Unlike activate(), call() requires the extension to be present before it can lazily activate it and look up the method on exports.

Source

Thrown at src/extension/manager.ts:360

    }
    disposeExtension(id)
  }

  public async reloadExtension(id: string): Promise<void> {
    let item = this.extensions.get(id)
    if (!item || item.type == ExtensionType.Internal) {
      throw new Error(`Extension ${id} not registered`)
    }
    if (item.type == ExtensionType.SingleFile) {
      await this.loadExtensionFile(item.filepath)
    } else {
      await this.loadExtension(item.directory)
    }
  }

  public async call(id: string, method: string, args: any[]): Promise<any> {
    let item = this.extensions.get(id)
    if (!item) throw new Error(`extension ${id} not registered`)
    let { extension } = item
    if (!extension.isActive) {
      await this.activate(id)
    }
    let { exports } = extension
    if (!exports || typeof exports[method] !== 'function') {
      throw new Error(`method ${method} not found on extension ${id}`)
    }
    return await Promise.resolve(exports[method].apply(null, args))
  }

  public registContribution(id: string, packageJSON: any, directory: string, filepath?: string): void {
    let { contributes, activationEvents } = packageJSON
    let { configuration, rootPatterns, commands } = contributes ?? {}
    let definitions: IStringDictionary<IJSONSchema> | undefined
    let props = getProperties(configuration ?? {})
    if (!isEmpty(props)) {
      // /configuration

View on GitHub (pinned to 50e974d969)

Solutions

  1. Verify the exact extension id against the installed extension's package.json `name`
  2. Load the extension first (loadExtension/loadExtensionFile) so it is registered before calling
  3. Check coc.extensions configuration — a disabled extension is not loaded and thus not registered
  4. Guard the call with getExtension(id) and handle the missing case gracefully

Example fix

// before
await manager.call('coc-myext', 'run', [])
// after
if (!manager.getExtension('coc-myext')) {
  await manager.loadExtension(dir)
}
await manager.call('coc-myext', 'run', [])
Defensive patterns

Strategy: validation

Validate before calling

if (!manager.getExtension(id)) {
  throw new Error(`extension ${id} must be loaded before call()`)
}

Try / catch

try {
  return await manager.call(id, method, args)
} catch (e) {
  if (e.message === `extension ${id} not registered`) {
    return undefined // feature optional
  }
  throw e
}

Prevention

When it happens

Trigger: Calling manager.call('coc-x', 'someMethod', args) where the id was never loaded, was unloaded, or is misspelled; also any RPC path (e.g. coc extension API call) targeting an unregistered id.

Common situations: Client code referencing an extension that failed to install; id changed between extension versions; calling from an autocmd/binding after the extension was disabled in configuration.

Related errors


AI-assisted analysis of neoclide/coc.nvim@50e974d969 (2026-08-31). Data as JSON: /api/errors/dab56eadebc2f7ac. Report an issue: GitHub.