risingwavelabs/risingwave · error · ConnectorError

credentials_url must be a valid URL (s3://, file://) or an a

Error message

credentials_url must be a valid URL (s3://, file://) or an absolute file path

What it means

Raised by `resolve_pulsar_credentials_url` when a Pulsar OAuth2 `credentials_url` is neither a parseable URL with scheme file:// or s3://, nor an absolute filesystem path. The function tries URL parsing first, then falls back to `Path::is_absolute`; both failing means the value cannot be resolved to a credentials file.

Source

Thrown at src/connector/src/connector_common/common.rs:752

        Ok(res)
    }

    pub(crate) async fn resolve_pulsar_credentials_url(
        &self,
        oauth: &PulsarOauthCommon,
        aws_auth_props: &AwsAuthProps,
    ) -> ConnectorResult<(String, Option<NamedTempFile>)> {
        // Try parsing as URL first
        if let Ok(url) = Url::parse(&oauth.credentials_url) {
            return self
                .handle_pulsar_credentials_url(&url, aws_auth_props)
                .await;
        }

        // If not a valid URL, check if it's an absolute file path
        let path = Path::new(&oauth.credentials_url);
        if !path.is_absolute() {
            bail!("credentials_url must be a valid URL (s3://, file://) or an absolute file path");
        }

        // Verify the file exists
        if !tokio::fs::try_exists(&oauth.credentials_url)
            .await
            .unwrap_or(false)
        {
            bail!("credentials file does not exist: {}", oauth.credentials_url);
        }

        // Return absolute path with file:// prefix
        Ok((format!("file://{}", oauth.credentials_url), None))
    }

    pub(crate) async fn handle_pulsar_credentials_url(
        &self,
        url: &Url,
        aws_auth_props: &AwsAuthProps,

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Use an absolute file path, e.g. `/etc/pulsar/creds.json`.
  2. Use a valid `file:///path/to/creds.json` or `s3://bucket/creds.json` URL.
  3. Fix scheme typos (e.g. `s3://` not `s3:/`) and ensure the value is non-empty.

Example fix

// before
credentials_url = "creds.json"
// after
credentials_url = "/etc/risingwave/pulsar/creds.json"
Defensive patterns

Strategy: validation

Validate before calling

function validateCredentialsUrl(v) {
  if (!v) throw new Error('credentials_url is empty');
  if (v.startsWith('/')) return; // absolute path ok
  try { const u = new URL(v); if (!['file:', 's3:'].includes(u.protocol)) throw new Error('bad scheme'); }
  catch { throw new Error(`credentials_url must be file://, s3://, or an absolute path, got: ${v}`); }
}
validateCredentialsUrl(oauth.credentials_url);

Type guard

const isAbsolutePath = (v) => typeof v === 'string' && v.startsWith('/');

Try / catch

try { await createPulsarSource(cfg); } catch (e) { if (String(e).includes('credentials_url must be a valid URL')) throw new Error('Fix credentials_url: use file:///abs/path, s3://bucket/key, or an absolute path'); throw e; }

Prevention

When it happens

Trigger: Setting `oauth.credentials_url` to a relative path like `creds.json`, an empty string, or a malformed URL (e.g. `s3:/bucket/file` missing a slash) while configuring a Pulsar source/sink with OAuth authentication.

Common situations: Using a relative path in config because it works locally but the process runs from a different working directory; typos in the URL scheme; copying credentials_url from another system with different path conventions.

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