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
- Ensure the path passed in is a fully-qualified remote URI including scheme, e.g. `s3://bucket/path/to/file.parquet`.
- Check the URI parses standalone (e.g. `url::Url::parse` or a quick manual check) — the embedded `{e}` names the exact parse defect.
- Use the catalog's own path-building helpers (`make_path`, `path_without_local_base`) instead of hand-concatenating strings.
- 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
- Always pass fully-qualified URIs (scheme://bucket/key) to remote catalog methods.
- Build paths with the catalog's make_path/URI helpers instead of string concatenation.
- Use a local catalog instance for filesystem paths; reserve remote catalogs for s3://, gs://, etc.
- Unit-test path construction with the same URI parser (url::Url::parse) the catalog uses.
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.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- URI {path} uses non-remote scheme {} for remote catalog at {
- Cross-store URI {path} (root {}) does not belong to catalog
- Invalid {description} endpoint
- {description} endpoint must use HTTPS or canonical loopback
- {description} endpoint host is required
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/e494f376d245993e.
Report an issue: GitHub.