{"record":{"id":"7ec077cf295a3968","repo":"charmbracelet/crush","slug":"invalid-uri-w","errorCode":null,"errorMessage":"invalid URI: %w","messagePattern":"invalid URI: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/lsp/util/edit.go","lineNumber":17,"sourceCode":"package util\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"os\"\n\t\"sort\"\n\t\"strings\"\n\n\tpowernap \"github.com/charmbracelet/x/powernap/pkg/lsp\"\n\t\"github.com/charmbracelet/x/powernap/pkg/lsp/protocol\"\n)\n\nfunc applyTextEdits(uri protocol.DocumentURI, edits []protocol.TextEdit, encoding powernap.OffsetEncoding) error {\n\tpath, err := uri.Path()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"invalid URI: %w\", err)\n\t}\n\n\t// Read the file content\n\tcontent, err := os.ReadFile(path)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to read file: %w\", err)\n\t}\n\n\t// Detect line ending style\n\tvar lineEnding string\n\tif bytes.Contains(content, []byte(\"\\r\\n\")) {\n\t\tlineEnding = \"\\r\\n\"\n\t} else {\n\t\tlineEnding = \"\\n\"\n\t}\n\n\t// Track if file ends with a newline\n\tendsWithNewline := len(content) > 0 && bytes.HasSuffix(content, []byte(lineEnding))","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/lsp/util/edit.go#L1-L35","documentation":"applyTextEdits converts a protocol.DocumentURI to a filesystem path via uri.Path() before reading the file and applying edits. If the URI is not a valid file-scheme URI (no extractable path), the error is wrapped as \"invalid URI\" and no edits are applied. It is reached from applyDocumentChange and ApplyWorkspaceEdit when handling server-initiated edits.","triggerScenarios":"applyTextEdits called (via applyDocumentChange or ApplyWorkspaceEdit) with a URI whose .Path() fails — e.g. an unscheme:// URI, a malformed URI from the server, or a URI for a non-file resource the client cannot map to disk.","commonSituations":"Server returns workspace edits referencing virtual/unsaved documents; URI strings copied from other tooling without file:// scheme; server bug emitting non-file URIs (e.g. untitled: buffers) in edits; version mismatch where the server encodes URIs unexpectedly.","solutions":["Filter workspace edit URIs and skip any whose scheme is not file:// before applying.","Check the server's edit payload (log the URI) to identify non-file resources.","Configure/upgrade the LSP server so edits only reference real file URIs.","Convert the resource to a file-backed document (save untitled buffers) before applying edits."],"exampleFix":"// before\nfor _, edit := range wsEdit.Changes {\n    applyTextEdits(edit.Uri, edit.Edits, enc) // may be non-file URI\n}\n\n// after\nif !strings.HasPrefix(string(edit.Uri), \"file://\") {\n    continue // skip non-file URIs\n}\napplyTextEdits(edit.Uri, edit.Edits, enc)","handlingStrategy":"type-guard","validationCode":"u, err := url.Parse(string(uri))\nif err != nil || u.Scheme != \"file\" {\n    return fmt.Errorf(\"skipping non-file URI: %s\", uri)\n}","typeGuard":"func isFileURI(uri protocol.DocumentURI) bool {\n    u, err := url.Parse(string(uri))\n    return err == nil && u.Scheme == \"file\"\n}","tryCatchPattern":"if err := applyWorkspaceEdit(ctx, wsEdit); err != nil {\n    if strings.Contains(err.Error(), \"invalid URI\") {\n        slog.Warn(\"Workspace edit contained a non-file URI; skipped\", \"error\", err)\n        return nil\n    }\n    return err\n}","preventionTips":["Sanitize all server-provided URIs for file scheme before applying edits.","Keep the LSP server updated; untitled/virtual-document edits are often server bugs.","Log raw workspace-edit payloads during integration to catch URI anomalies early."],"tags":["lsp","uri","workspace-edit"],"backgroundTag":"invalid-uri-scheme","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}