neoclide/coc.nvim · error · ResourceNotFoundError

${e instanceof Error ? e.message : String(e)}

Error message

${e instanceof Error ? e.message : String(e)}

What it means

For a `coc://document/<uri>` resource backed by a real file (not an open document), the server reads the file from disk with `fs.readFileSync`. Any filesystem failure (ENOENT, EACCES, EISDIR) is wrapped into a `ResourceNotFoundError` with the underlying error message.

Source

Thrown at src/mcp/resources.ts:82

        name: 'Document content',
        description: 'Text content of an editor document (file URI encoded as parameter).'
      }]
    }
  }

  public async read(uri: string): Promise<{ contents: ResourceContent[] }> {
    if (uri.startsWith(DOCUMENT_PREFIX)) {
      let fileUri = decodeURIComponent(uri.slice(DOCUMENT_PREFIX.length))
      let ref = await resolveDocument(fileUri, false)
      if (ref.error) throw new ResourceNotFoundError(ref.error)
      let text: string
      if (ref.doc) {
        text = ref.doc.getDocumentContent()
      } else {
        try {
          text = fs.readFileSync(toFsPath(fileUri), 'utf8')
        } catch (e) {
          throw new ResourceNotFoundError(e instanceof Error ? e.message : String(e))
        }
      }
      return { contents: [{ uri, mimeType: 'text/plain', text }] }
    }
    switch (uri) {
      case 'coc://diagnostics': {
        let list = await diagnosticManager.getDiagnosticList()
        return { contents: [{ uri, mimeType: 'application/json', text: JSON.stringify(list, null, 2) }] }
      }
      case 'coc://services': {
        let stats = services.getServiceStats().map(stat => {
          let service = services.getService(stat.id)
          let init = service?.client?.initializeResult
          return {
            id: stat.id,
            state: stat.state,
            languageIds: stat.languageIds,
            capabilities: init?.capabilities ?? null

View on GitHub (pinned to 50e974d969)

Solutions

  1. Check the exact message (ENOENT vs EACCES vs EISDIR) to identify the filesystem problem
  2. Verify the file exists and is readable at the encoded path
  3. Re-list resources to refresh URIs after files moved
  4. Do not wrap the encoded URI again (double-encoding produces a wrong path)

Example fix

// before
await read('coc://document/' + encodeURIComponent('file:///missing.txt')) // double-encoded
// after
await read(URI.file('/missing.txt').toString().replace('file://', 'coc://document/'))
Defensive patterns

Strategy: try-catch

Validate before calling

const fileUri = decodeURIComponent(uri.slice('coc://document/'.length))
const stat = fs.existsSync(toFsPath(fileUri)) ? fs.statSync(toFsPath(fileUri)) : null
if (!stat) throw new Error(`File not found: ${fileUri}`)
if (!stat.isFile()) throw new Error(`Not a regular file: ${fileUri}`)

Try / catch

try {
  const res = await resources.read(uri)
} catch (e) {
  if (/ENOENT/.test(e.message)) logger.warn(`File gone: ${uri}`)
  else if (/EACCES/.test(e.message)) logger.error(`Permission denied: ${uri}`)
  else if (/EISDIR/.test(e.message)) logger.error(`URI points to a directory: ${uri}`)
  else throw e
}

Prevention

When it happens

Trigger: `resources.read('coc://document/<file-uri>')` where the file does not exist, lacks read permission, or the URI points to a directory — the readFileSync throws and the message (e.g. 'ENOENT: no such file or directory') becomes the error text.

Common situations: File deleted or moved after being listed as a resource; wrong absolute path in the URI; permission issues when the server runs as a different user; passing a directory instead of a file.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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