risingwavelabs/risingwave · error · anyhow::Error

Invalid warehouse path: {}

Error message

Invalid warehouse path: {}

What it means

`build_storage_catalog_config` parses `warehouse.path` with the `url::Url` crate; a parse failure (unparseable, scheme-less string like '/local/path' or 'my-bucket/wh') bails with the raw value embedded in the message.

Source

Thrown at src/connector/src/connector_common/iceberg/mod.rs:619

            return false;
        }
        self.enable_config_load.unwrap_or(false)
    }

    fn effective_s3_path_style_access(&self) -> bool {
        // RisingWave historically inherited OpenDAL's path-style default. Iceberg now
        // defaults to virtual-host style, so preserve existing connector behavior unless
        // the user explicitly opts into virtual-host style with `false`.
        self.s3_path_style_access.unwrap_or(true)
    }

    fn build_storage_catalog_config(&self) -> ConnectorResult<CatalogBuildPlan> {
        let warehouse = self
            .warehouse_path
            .clone()
            .ok_or_else(|| anyhow!("`warehouse.path` must be set in storage catalog"))?;
        let url = Url::parse(warehouse.as_ref())
            .map_err(|_| anyhow!("Invalid warehouse path: {}", warehouse))?;

        let config = match url.scheme() {
            "s3" | "s3a" => StorageCatalogConfig::S3(
                storage_catalog::StorageCatalogS3Config::builder()
                    .warehouse(warehouse)
                    .access_key(self.s3_access_key.clone())
                    .secret_key(self.s3_secret_key.clone())
                    .region(self.s3_region.clone())
                    .endpoint(self.s3_endpoint.clone())
                    .path_style_access(Some(self.effective_s3_path_style_access()))
                    .enable_config_load(Some(self.enable_config_load()))
                    .build(),
            ),
            "gs" | "gcs" => StorageCatalogConfig::Gcs(
                storage_catalog::StorageCatalogGcsConfig::builder()
                    .warehouse(warehouse)
                    .credential(self.gcs_credential.clone())
                    .enable_config_load(Some(self.enable_config_load()))

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Use a fully qualified URI: 's3://bucket/warehouse', 's3a://bucket/warehouse', or an azblob URL.
  2. Fix scheme typos (s3:// with two slashes) and URL-encode special characters.
  3. If you intended a local path, note storage catalog requires an object-store scheme; use a supported backend.

Example fix

// before
warehouse.path = '/data/warehouse'
// after
warehouse.path = 's3://my-bucket/data/warehouse'
Defensive patterns

Strategy: validation

Validate before calling

try { new URL(opts['warehouse.path']); } catch { throw new Error(`Invalid warehouse path: ${opts['warehouse.path']}`); }

Type guard

const isValidUrl = (s) => { try { new URL(s); return true; } catch { return false; } };

Prevention

When it happens

Trigger: `warehouse.path` given as a bare filesystem path, missing scheme ('bucket/warehouse'), or containing characters illegal in a URL.

Common situations: Using local paths instead of s3:// URIs; forgetting the scheme; typos like 's3:/bucket' (single slash); unencoded spaces or special characters in bucket keys.

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 risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/6e498b223f1bbd61. Report an issue: GitHub.