neoclide/coc.nvim · error

required capabilities do not exist.

Error message

required capabilities do not exist.

What it means

Watchman.createClient connects to the watchman binary and calls checkCapability(); if the installed watchman does not report the required capabilities (required defined via watchman capability checks), the client is disposed and this error is thrown. It means the watchman version on the system is too old or lacks needed features.

Source

Thrown at src/core/watchman.ts:160

  public dispose(): void {
    if (this.client) {
      this.client.end()
      this.client = undefined
    }
  }

  private appendOutput(message: string, type = "Info"): void {
    if (this.channel) {
      this.channel.appendLine(`[${type}  - ${(new Date().toLocaleTimeString())}] ${message}`)
    }
  }

  public static async createClient(binaryPath: string, root: string, channel?: OutputChannel): Promise<Watchman> {
    let watchman: Watchman
    try {
      watchman = new Watchman(binaryPath, channel)
      let valid = await watchman.checkCapability()
      if (!valid) throw new Error('required capabilities do not exist.')
      let watching = await watchman.watchProject(root)
      if (!watching) throw new Error('unable to watch')
      return watchman
    } catch (e) {
      if (watchman) watchman.dispose()
      throw e
    }
  }
}

View on GitHub (pinned to 50e974d969)

Solutions

  1. Install/upgrade watchman to a recent version (e.g. brew install watchman or build from source).
  2. Verify with 'watchman version' that the binary at the configured path supports the needed capabilities.
  3. Remove the old binaryPath configuration so coc.nvim finds the up-to-date watchman on PATH.
  4. Restart the watchman service (watchman shutdown-server) if a stale server is answering.

Example fix

// before
let wm = await Watchman.createClient('/usr/bin/old-watchman', root)
// throws 'required capabilities do not exist.'
// after
let wm = await Watchman.createClient('/opt/homebrew/bin/watchman', root) // recent watchman
Defensive patterns

Strategy: validation

Validate before calling

const { execFile } = require('child_process')
function checkWatchman(binaryPath) {
  return new Promise((resolve) => {
    execFile(binaryPath, ['version'], (err, stdout) => {
      if (err) return resolve(false)
      try { resolve(JSON.parse(stdout).version ? true : false } catch { resolve(false) }
    })
  })
}
// only call Watchman.createClient if checkWatchman returns true and version is recent

Try / catch

try {
  const wm = await Watchman.createClient(binaryPath, root)
} catch (e) {
  if (e.message === 'required capabilities do not exist.') {
    logger.error('watchman too old; install >= 4.9 via brew install watchman')
    // fall back to fs.watch-based watching
  } else throw e
}

Prevention

When it happens

Trigger: Watchman.createClient(binaryPath, root, channel) where await watchman.checkCapability() returns false because the watchman server at binaryPath lacks the required capabilities (e.g. wildcard support, term-based queries).

Common situations: Old system watchman (< 3.x) installed via package manager; watchman binary at a custom binaryPath is stale; multiple watchman versions on PATH; watchman service returning errors that make capability checks fail.

Related errors


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