{"record":{"id":"6f46909a3cd64e14","repo":"nautechsystems/nautilus_trader","slug":"replace-existing-for-remote-streaming-paths-requir","errorCode":null,"errorMessage":"replace_existing for remote streaming paths requires a non-empty prefix","messagePattern":"replace_existing for remote streaming paths requires a non-empty prefix","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/persistence/src/backend/feather.rs","lineNumber":302,"sourceCode":"        rotation_config: RotationConfig,\n        included_types: Option<HashSet<String>>,\n        flush_interval_ms: Option<u64>,\n        replace_existing: bool,\n    ) -> anyhow::Result<Self> {\n        let normalized_uri = crate::parquet::normalize_path_to_uri(uri);\n        if normalized_uri.starts_with(\"file://\") {\n            let path = crate::parquet::file_uri_to_native_path(&normalized_uri);\n            std::fs::create_dir_all(&path)\n                .with_context(|| format!(\"Failed to create streaming directory '{path}'\"))?;\n        }\n        let location = create_object_store_location_from_path(&normalized_uri, storage_options)?;\n        let is_local = matches!(location.kind, ObjectStoreLocationKind::Local);\n        let store = location.object_store;\n        let base_path = location.base_path;\n\n        if replace_existing {\n            let prefix = if base_path.is_empty() {\n                anyhow::ensure!(\n                    is_local,\n                    \"replace_existing for remote streaming paths requires a non-empty prefix\",\n                );\n                None\n            } else {\n                Some(Path::from(base_path.clone()))\n            };\n            let runtime = nautilus_common::live::get_runtime();\n            runtime.block_on(async {\n                let mut objects = store.list(prefix.as_ref());\n                let mut paths = Vec::new();\n                while let Some(result) = objects.next().await {\n                    paths.push(result?.location);\n                }\n\n                for path in paths {\n                    store.delete(&path).await?;\n                }","sourceCodeStart":284,"sourceCodeEnd":320,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/persistence/src/backend/feather.rs#L284-L320","documentation":"Thrown by FeatherQueryResult::from_uri when replace_existing is requested for a remote object store with an empty base_path. Deleting existing data on a remote store requires an explicit prefix to scope the deletion; deleting with no prefix on a remote store would be dangerously broad, so it is only allowed for local paths (where the catalog directory itself scopes it).","triggerScenarios":"Constructing a streaming query/write URI against a remote object store (S3, GCS, etc.) with replace_existing=true and an empty base_path prefix.","commonSituations":"Config mistakes where the remote URI omitted the bucket key/prefix portion; copying local-path configuration to a cloud store without adding the base path; tests that always used local paths now pointed at remote storage.","solutions":["Provide a non-empty base_path/prefix in the object store location when using replace_existing with a remote store.","Set replace_existing=false if you don't need to delete prior data on the remote store.","If targeting local paths only, keep the empty base_path but confirm location.kind is Local.","Scope deletions by writing into a dedicated prefix directory and replacing only that."],"exampleFix":"// before\nlet uri = \"s3://bucket\"; // empty prefix + replace_existing\n// after\nlet uri = \"s3://bucket/data/strategy_a\"; // non-empty prefix for replace_existing","handlingStrategy":"validation","validationCode":"if replace_existing && !is_local && base_path.is_empty() {\n    panic!(\"remote replace_existing requires a non-empty base_path prefix\");\n}","typeGuard":"fn can_replace_existing(kind: &ObjectStoreLocationKind, base_path: &str) -> bool {\n    matches!(kind, ObjectStoreLocationKind::Local) || !base_path.is_empty()\n}","tryCatchPattern":"match FeatherQueryResult::from_uri(uri, replace_existing) {\n    Ok(r) => use(r),\n    Err(e) if e.to_string().contains(\"non-empty prefix\") => eprintln!(\"add a base path to the remote URI\"),\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Always include a key/prefix in remote object store URIs","Only use replace_existing=true with a scoped prefix","Avoid copying local-path configs directly to remote stores","Prefer writing into dedicated per-strategy prefixes for safe replacement"],"tags":["rust","persistence","object-store","configuration"],"backgroundTag":"invalid-config-value","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}