charmbracelet/crush · error

failed to apply text edits: %w

Error message

failed to apply text edits: %w

What it means

ApplyWorkspaceEdit iterates the WorkspaceEdit.Changes map (uri -> []TextEdit) and applies each set with applyTextEdits. Any failure there (missing document, bad positions, IO error) is wrapped as "failed to apply text edits". The Changes field is the legacy/simpler shape of a WorkspaceEdit as opposed to DocumentChanges.

Source

Thrown at internal/lsp/util/edit.go:273

	var codepointCount uint32
	for byteOffset := range lineText {
		if codepointCount >= codepointOffset {
			return byteOffset
		}
		codepointCount++
	}
	return len(lineText)
}

// ApplyWorkspaceEdit applies the given WorkspaceEdit to the filesystem.
// The encoding parameter specifies the position encoding used by the LSP server
// (UTF8, UTF16, or UTF32). This affects how character offsets are interpreted.
func ApplyWorkspaceEdit(edit protocol.WorkspaceEdit, encoding powernap.OffsetEncoding) error {
	// Handle Changes field
	for uri, textEdits := range edit.Changes {
		if err := applyTextEdits(uri, textEdits, encoding); err != nil {
			return fmt.Errorf("failed to apply text edits: %w", err)
		}
	}

	// Handle DocumentChanges field
	for _, change := range edit.DocumentChanges {
		if err := applyDocumentChange(change, encoding); err != nil {
			return fmt.Errorf("failed to apply document change: %w", err)
		}
	}

	return nil
}

// rangesOverlap checks if two LSP ranges overlap.
// Per the LSP specification, ranges are half-open intervals [start, end),
// so adjacent ranges where one's end equals another's start do NOT overlap.
// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#range
func rangesOverlap(r1, r2 protocol.Range) bool {

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Read the wrapped inner error to see whether it is a range/position or IO problem
  2. Ensure the document is open/registered with the LSP client before applying edits
  3. Pass the correct OffsetEncoding negotiated with the server
  4. Reload the file and re-request the edit if it changed since it was produced

Example fix

// before
err := ApplyWorkspaceEdit(edit, powernap.EncodingUTF16)
// after
if err := ApplyWorkspaceEdit(edit, serverNegotiatedEncoding); err != nil {
    if strings.Contains(err.Error(), "apply text edits") {
        // reload document and retry
    }
    return err
}
Defensive patterns

Strategy: try-catch

Validate before calling

for uri, edits := range edit.Changes {
    doc, ok := openDocs[uri]
    if !ok {
        return fmt.Errorf("document not open: %s", uri)
    }
    for _, e := range edits {
        if e.Range.End.Line > uint32(len(doc.Lines())) {
            return fmt.Errorf("range out of bounds for %s", uri)
        }
    }
}

Try / catch

if err := ApplyWorkspaceEdit(edit, enc); err != nil {
    var inner error
    for e := err; e != nil; e = errors.Unwrap(e) { inner = e }
    log.Printf("text edits failed for %s: %v", uriOf(edit), inner)
}

Prevention

When it happens

Trigger: Server returns WorkspaceEdit.Changes entries and applyTextEdits fails, e.g. the target URI is not open/known so its content cannot be read, or the edit's range exceeds the document bounds.

Common situations: Edits referencing a file the client never opened; encoding mismatch (UTF-8 vs UTF-16 offsets from OffsetEncoding) producing out-of-range positions; file changed on disk since the server computed the edit; diagnostics-quickfix applied to a file that was modified.

Related errors


AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29). Data as JSON: /api/errors/e1448352ea80de4a. Report an issue: GitHub.