denoland/deno · error

Unable to convert document highlights: {:#}

Error message

Unable to convert document highlights: {:#}

What it means

After tsc returns document highlights (occurrences of the symbol under the cursor), each is converted to an LSP highlight range with to_highlight; this wraps a conversion failure. The common root cause is a highlight span that fails to map through the module's line index, typically because the document changed between the tsc query and the conversion, or conversion was cancelled mid-way.

Source

Thrown at cli/lsp/ts_server.rs:528

    token: &CancellationToken,
  ) -> Result<Option<Vec<lsp::DocumentHighlight>>, AnyError> {
    match self {
      Self::Js(ts_server) => {
        let highlights = ts_server
          .get_document_highlights(
            snapshot,
            module,
            module.line_index.offset_tsc(position)?,
            token,
          )
          .await?;
        highlights
          .map(|highlights| {
            highlights
              .into_iter()
              .map(|dh| {
                dh.to_highlight(&module.line_index, token).map_err(|err| {
                  anyhow!("Unable to convert document highlights: {:#}", err)
                })
              })
              .collect::<Result<Vec<_>, _>>()
              .map(|s| s.into_iter().flatten().collect())
          })
          .transpose()
      }
    }
  }

  pub async fn provide_definition(
    &self,
    module: &DocumentModule,
    position: lsp::Position,
    snapshot: &Arc<StateSnapshot>,
    token: &CancellationToken,
  ) -> Result<Option<lsp::GotoDefinitionResponse>, AnyError> {
    match self {

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Let edits settle and trigger the highlight again (move the cursor) — nearly always transient.
  2. Save the file to force a full sync, then retry.
  3. Run "Deno: Restart Language Server" if highlights stay broken for a file.
  4. Update Deno; check the wrapped error text in the language server output if it persists.
Defensive patterns

Strategy: retry

Try / catch

// Highlight failures stem from stale line-index mappings; the next
// request after edits settle succeeds.
async function highlightsWithRetry(client, params) {
  try {
    return await client.sendRequest('textDocument/documentHighlight', params);
  } catch (err) {
    if (String(err?.message).includes('document highlights')) {
      await sleep(250);
      return await client.sendRequest('textDocument/documentHighlight', params);
    }
    throw err;
  }
}

Prevention

When it happens

Trigger: A textDocument/documentHighlight request where a returned span is out of bounds for the current line index — rapid edits between request and conversion, a stale snapshot, or cancellation during the mapping loop.

Common situations: Selecting/typing over occurrences while highlight requests are in flight; failures appearing intermittently during fast editing and disappearing on the next request.

Related errors


AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20). Data as JSON: /api/errors/cbbfc89a40e96602. Report an issue: GitHub.