nautechsystems/nautilus_trader · error · anyhow::Error

Failed to parse object store URI {path}: {e}

Error message

Failed to parse object store URI {path}: {e}

What it means

Raised in `remote_uri_object_path` when the path given to the remote catalog cannot be parsed as a URL by the `url` crate. The remote catalog expects every path to be a well-formed URI (e.g. `s3://bucket/key`); the original parse error is embedded in the message after the offending path.

Source

Thrown at crates/persistence/src/backend/catalog.rs:3052

    fn object_store_path(&self, path: &str) -> anyhow::Result<String> {
        let normalized_path = path.replace('\\', "/");

        if self.is_remote_uri() {
            if normalized_path.contains("://") {
                let path_under_root = self.remote_uri_object_path(&normalized_path)?;
                return Ok(self.path_under_base(&path_under_root));
            }

            return Ok(self.path_under_base(&normalized_path));
        }

        Ok(self.path_without_local_base(&normalized_path))
    }

    fn remote_uri_object_path(&self, path: &str) -> anyhow::Result<String> {
        let path_url = url::Url::parse(path)
            .map_err(|e| anyhow::anyhow!("Failed to parse object store URI {path}: {e}"))?;
        if !is_remote_uri_scheme(path_url.scheme()) {
            anyhow::bail!(
                "URI {path} uses non-remote scheme {} for remote catalog at {}",
                path_url.scheme(),
                self.original_uri,
            );
        }

        let catalog_root = remote_store_root_url(&self.original_uri)?;
        let path_root = remote_store_root_url(path)?;
        if catalog_root.as_str().trim_end_matches('/') != path_root.as_str().trim_end_matches('/') {
            anyhow::bail!(
                "Cross-store URI {path} (root {}) does not belong to catalog rooted at {} ({})",
                path_root.as_str().trim_end_matches('/'),
                self.original_uri,
                catalog_root.as_str().trim_end_matches('/'),
            );
        }

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Ensure the path passed in is a fully-qualified remote URI including scheme, e.g. `s3://bucket/path/to/file.parquet`.
  2. Check the URI parses standalone (e.g. `url::Url::parse` or a quick manual check) — the embedded `{e}` names the exact parse defect.
  3. Use the catalog's own path-building helpers (`make_path`, `path_without_local_base`) instead of hand-concatenating strings.
  4. If a local path is intended, construct the catalog as a local (non-remote) catalog so `remote_uri_object_path` is not used.

Example fix

// before
let path = catalog.object_store_path("data/quotes.parquet")?; // no scheme

// after
let path = catalog.object_store_path("s3://my-bucket/data/quotes.parquet")?;
Defensive patterns

Strategy: validation

Validate before calling

fn ensure_remote_uri(path: &str) -> Result<(), String> {
    match url::Url::parse(path) {
        Ok(u) if matches!(u.scheme(), "s3" | "gs" | "az" | "abfs" | "https" | "file") => Ok(()),
        Ok(u) => Err(format!("scheme '{}' not remote-capable", u.scheme())),
        Err(e) => Err(format!("not a valid URI: {e}")),
    }
}

Type guard

fn is_remote_uri(path: &str) -> bool {
    url::Url::parse(path).map(|u| !u.scheme().is_empty() && path.contains("://")).unwrap_or(false)
}

Prevention

When it happens

Trigger: Calling `object_store_path` (or any path-resolution entry point) on a remote `ParquetDataCatalog` with a string that is not a valid absolute URI — e.g. a plain filesystem path like `/data/catalog/quotes.parquet` or a malformed scheme like `s3:/bucket/key`.

Common situations: Constructing the catalog with a remote URI (s3://, gs://, abfs://) but then passing local-style relative paths to query/write methods; typo'd or double/unbalanced slashes in the scheme; path built by string concatenation that dropped the scheme prefix; copy-pasting a path without the URI.

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 nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/e494f376d245993e. Report an issue: GitHub.