risingwavelabs/risingwave · error · SinkError::DeltaLake

Url parse error for GCS deltalake location (wrapped error)

Error message

Url parse error for GCS deltalake location (wrapped error)

What it means

Error in create_deltalake_client when constructing the GCS deltalake table URL: the local/GCS path could not be parsed into a valid Url (the wrapped underlying parse error carries the cause). It indicates the configured deltalake location string is malformed (bad characters, missing scheme handling) rather than a connectivity problem.

Source

Thrown at src/connector/src/sink/deltalake.rs:122

                deltalake::open_table_with_storage_options(url, storage_options).await?
            }
            DeltaTableUrl::Local(local_path) => {
                let url = Url::parse(&format!("file://{}", local_path))
                    .map_err(|e| SinkError::DeltaLake(anyhow!(e)))?;
                deltalake::open_table(url).await?
            }
            DeltaTableUrl::Gcs(gcs_path) => {
                let mut storage_options = HashMap::new();
                storage_options.insert(
                    GCS_SERVICE_ACCOUNT.to_owned(),
                    self.gcs_service_account.clone().ok_or_else(|| {
                        SinkError::Config(anyhow!(
                            "gcs.service.account is required with Google Cloud Storage (GCS)"
                        ))
                    })?,
                );
                deltalake::gcp::register_handlers(None);
                let url = Url::parse(&gcs_path).map_err(|e| SinkError::DeltaLake(anyhow!(e)))?;
                deltalake::open_table_with_storage_options(url, storage_options).await?
            }
        };
        Ok(table)
    }

    fn get_table_url(path: &str) -> Result<DeltaTableUrl> {
        if path.starts_with("s3://") || path.starts_with("s3a://") {
            Ok(DeltaTableUrl::S3(path.to_owned()))
        } else if path.starts_with("gs://") {
            Ok(DeltaTableUrl::Gcs(path.to_owned()))
        } else if let Some(path) = path.strip_prefix("file://") {
            Ok(DeltaTableUrl::Local(path.to_owned()))
        } else {
            Err(SinkError::DeltaLake(anyhow!(
                "path should start with 's3://','s3a://'(s3) ,gs://(gcs) or file://(local)"
            )))
        }

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Use a well-formed gs://bucket/path URL as the location.
  2. Trim whitespace and replace backslashes with forward slashes.
  3. Percent-encode any special characters in object keys.

Example fix

// before
LOCATION = 'gs://bucket/my table'
// after
LOCATION = 'gs://bucket/my-table'
Defensive patterns

Strategy: validation

Validate before calling

let loc = location.trim();
if !loc.starts_with("gs://") {
    return Err("GCS deltalake location must start with gs://");
}
Url::parse(loc).map_err(|e| format!("invalid GCS URL: {e}"))?;

Prevention

When it happens

Trigger: create_deltalake_client with DeltaTableUrl::Gcs whose gs:// path fails Url::parse — e.g. 'gs://bucket\path', spaces, or control characters.

Common situations: Malformed bucket/object names; whitespace or newlines introduced when pasting the location; backslashes from Windows-style paths.

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/6ccb8a9b145e665d. Report an issue: GitHub.