Automattic/harper · error · anyhow::Error
Unable to convert URL to file path.
Error message
Unable to convert URL to file path.
What it means
`update_document_from_file` converts an LSP document URI to a filesystem path with `uri.to_file_path()`. This returns None for URIs that are not `file://` (e.g. untitled:, remote/virtual schemes), and the code bails with "Unable to convert URL to file path." before attempting the read.
Source
Thrown at harper-ls/src/backend.rs:231
async fn generate_file_dictionary(&self, uri: &Uri) -> Result<MergedDictionary> {
let (global_dictionary, file_dictionary) = tokio::join!(
self.generate_global_dictionary(),
self.load_file_dictionary(uri)
);
let mut global_dictionary =
global_dictionary.context("Unable to load the user dictionary.")?;
global_dictionary.add_dictionary(Arc::new(
file_dictionary.context("Unable to load the file dictionary.")?,
));
Ok(global_dictionary)
}
async fn update_document_from_file(&self, uri: &Uri, language_id: Option<&str>) -> Result<()> {
let content = tokio::fs::read_to_string(
uri.to_file_path()
.ok_or_else(|| anyhow!("Unable to convert URL to file path."))?,
)
.await
.with_context(|| format!("Unable to read from file {uri:?}"))?;
self.update_document(uri, &content, language_id).await
}
async fn update_document(
&self,
uri: &Uri,
text: &str,
language_id: Option<&str>,
) -> Result<()> {
self.pull_config().await;
// Copy necessary configuration to avoid holding lock.
let (
lint_config,View on GitHub (pinned to 5fe7d5ab76)
Solutions
- Save the buffer so it has a real file:// URI before triggering the reload.
- Skip/ignore the update for non-file schemes; only pass file:// URIs to this path.
- For remote development, ensure harper-ls runs on the same host as the files so file:// URIs resolve.
- Percent-encode the URI properly; malformed file URIs (bad authority) also fail to_file_path.
Example fix
// before (client sends) untitled:Untitled-1 // after // save the document first so the URI becomes file:///home/user/project/Untitled-1.ts
Defensive patterns
Strategy: type-guard
Validate before calling
function isFileUri(uri) {
try { const u = new URL(uri); return u.protocol === 'file:'; } catch { return false; }
} Type guard
function canConvertToFilePath(uri) {
return uri.startsWith('file://') && !uri.startsWith('file://'); // no-op guard placeholder
} Try / catch
try {
await reloadDocument(uri);
} catch (err) {
if (String(err.message).includes('Unable to convert URL to file path')) {
// non-file or malformed URI; save the buffer or skip virtual documents
}
} Prevention
- Save unsaved buffers before triggering reload commands
- Filter out non-file schemes (untitled:, remote:, custom) before sending to harper-ls
- Run the language server on the same host/filesystem as the documents
- Percent-encode file URIs correctly
When it happens
Trigger: Calling the relopen/execute_command path or did_change_configuration-triggered refresh with a URI like `untitled:Untitled-1`, `remote://...`, `zip://...`, or any non-file scheme; also malformed file URIs without a host/authority that Rust's to_file_path rejects.
Common situations: Editor buffers not backed by a file (new unsaved documents), remote-development (SSH/WSL/container) virtual filesystems, or extensions that expose documents through custom schemes.
Understand the failure class
Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.
Related errors
- Unable to convert URI to file path.
- Unable to convert URI to file path.
- The code action configuration must be an object.
- ForceStable must be a boolean value.
- Settings must be an object.
AI-assisted analysis of Automattic/harper@5fe7d5ab76 (2026-09-06).
Data as JSON: /api/errors/bb102877957654b9.
Report an issue: GitHub.