sinelaw/fresh · error

URI is not a file path (container-side decode failed)

Error message

URI is not a file path (container-side decode failed)

What it means

In open_lsp_uri_target's container branch (a translation/authority is active), the code decodes the URI's raw path verbatim to run `cat <path>` inside the container. If uri.to_host_path(None) returns None — the URI has no decodable file path — this error is thrown before any container command runs.

Solutions

  1. Log and inspect the incoming LspUri; confirm it is a file:// URI with a non-empty path
  2. Handle virtual-document schemes separately instead of treating them as container paths
  3. Check the LSP server version/config for options that emit plain file paths
  4. Fall back to Case 1 (host path) semantics or surface a friendly message when the URI is not a file

Example fix

// before
let container_path = uri.to_host_path(None).ok_or_else(|| {
    anyhow::anyhow!("URI is not a file path (container-side decode failed)")
})?;
// after
let Some(container_path) = uri.to_host_path(None) else {
    log::warn!("skipping non-file LSP URI: {}", uri.as_str());
    return Ok(self.active_buffer_id());
};
Defensive patterns

Strategy: validation

Validate before calling

if translation.is_some() && uri.to_host_path(None).is_none() {
    // skip container fetch, show message instead
}

Type guard

fn container_path_of(uri: &LspUri) -> Option<std::path::PathBuf> {
    uri.to_host_path(None)
}

Try / catch

match self.open_lsp_uri_target(&uri) {
    Err(e) if e.to_string().contains("container-side decode failed") => {
        log::warn!("cannot fetch non-file URI from container: {}", uri.as_str());
    }
    other => other?,
}

Prevention

When it happens

Trigger: goto-definition returns a non-file:// or malformed URI while the editor is attached to a devcontainer/remote authority, so the container-side decode of the URI path fails.

Common situations: Remote development against a language server that reports definitions with virtual or custom URI schemes; a corrupt URI produced by a buggy server over the wire.

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


AI-assisted analysis of sinelaw/fresh@67894ca546 (2026-09-13). Data as JSON: /api/errors/95dc79f958f06a14. Report an issue: GitHub.

Appendix: source

Thrown at crates/fresh-editor/src/app/file_open_orchestrators.rs:708

        // `open_file` focuses, which is what callers (goto-def,
        // workspace edits) expect — they want the cursor to land in
        // the destination buffer afterward.
        if self.authority().filesystem.exists(&host_path) {
            return self.open_file(&host_path);
        }

        // Case 2: container-only fetch. Only meaningful when the
        // active authority can route a `cat` through to the
        // container — `path_translation` being set is the proxy for
        // "this is a container authority". Local + SSH authorities
        // skip straight to the error case.
        if translation.is_some() {
            // The container-side path is the URI's raw path. Calling
            // `to_host_path` with `None` returns the wire-side path
            // verbatim (no translation applied) — exactly what we
            // need for `cat <path>` inside the container.
            let container_path = uri.to_host_path(None).ok_or_else(|| {
                anyhow::anyhow!("URI is not a file path (container-side decode failed)")
            })?;
            let buffer_id = self.fetch_and_open_container_file(container_path, uri.clone())?;
            // Match `open_file`'s focus behaviour so the cursor
            // assertion in callers (goto-def's `MoveCursor` event)
            // applies to the right buffer.
            self.set_active_buffer(buffer_id);
            return Ok(buffer_id);
        }

        // Case 3: nothing we can open.
        Err(anyhow::anyhow!(
            "could not open {}: file not found",
            host_path.display()
        ))
    }

    /// Run `cat <container_path>` through the active authority's
    /// process spawner and open the result as a read-only buffer

View on GitHub (pinned to 67894ca546)