databendlabs/databend · error · Error

Failed to get or create operator

Error message

Failed to get or create operator: {}

What it means

init_operator_with_policy_scope consults the process-wide operator cache (get_operator_cache().get_or_create) keyed by StorageParams and policy scope; this error wraps any failure of that construction. It is the common funnel through which storage misconfigurations surface when initializing an Operator for tables, stages, or attach requests.

Solutions

  1. Read the wrapped inner error ({}) — it names the concrete opendal failure (config invalid, connection refused, auth).
  2. Validate the [storage] section of the query config: endpoint, bucket, root, credentials.
  3. Test connectivity to the storage endpoint from the node (curl the endpoint / aws s3 ls).
  4. Restart/retry after fixing config; operators are cached, so a config fix requires rebuilding the operator (process restart or cache invalidation).

Example fix

// before (config)
[storage]
type = "s3"
[storage.s3]
bucket = ""
// after
[storage.s3]
bucket = "my-bucket"
endpoint_url = "https://s3.us-east-1.amazonaws.com"
Defensive patterns

Strategy: try-catch

Validate before calling

// Rust: sanity-check StorageParams before initializing
if let StorageParams::S3(cfg) = &storage_params {
    assert!(!cfg.bucket.is_empty(), "s3 bucket required");
    assert!(!cfg.endpoint_url.is_empty(), "s3 endpoint required");
}

Try / catch

match init_operator(&storage_params).await {
    Ok(op) => op,
    Err(e) => {
        tracing::error!("operator init failed: {e}");
        return Err(e);
    }
}

Prevention

When it happens

Trigger: Calling init_operator, init_stage_operator, build_attach_table_request, or executor bind_create_table/bind_attach_table with a StorageParams whose endpoint is unreachable, credentials invalid, bucket missing, or whose opendal config fails validation during operator build.

Common situations: Wrong S3 endpoint/region in the databend query config; expired or incorrect access keys; DNS failure resolving the storage endpoint; operator cache build racing with config reload.

Understand the failure class

Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.

Related errors


AI-assisted analysis of databendlabs/databend@288d84d76e (2026-09-11). Data as JSON: /api/errors/75fc37eae87c5c29. Report an issue: GitHub.

Appendix: source

Thrown at src/common/storage/src/operator.rs:87

static METRIC_OPENDAL_RETRIES_COUNT: LazyLock<FamilyCounter<Vec<(&'static str, String)>>> =
    LazyLock::new(|| register_counter_family("opendal_retries_count"));

/// init_operator will init an opendal operator based on storage config.
pub fn init_operator(cfg: &StorageParams) -> Result<Operator> {
    init_operator_with_policy_scope(cfg, EndpointPolicyScope::Trusted)
}

/// init_operator_with_policy_scope will init an opendal operator with an
/// explicit endpoint egress policy scope.
pub fn init_operator_with_policy_scope(
    cfg: &StorageParams,
    endpoint_policy_scope: EndpointPolicyScope,
) -> Result<Operator> {
    let cache = get_operator_cache();
    cache
        .get_or_create(cfg, endpoint_policy_scope)
        .map_err(|e| Error::other(anyhow!("Failed to get or create operator: {}", e)))
}

/// init_operator_uncached will init an opendal operator without caching.
/// This function creates a new operator every time it's called.
pub(crate) fn init_operator_uncached(
    cfg: &StorageParams,
    endpoint_policy_scope: EndpointPolicyScope,
) -> Result<Operator> {
    let op = match &cfg {
        StorageParams::Azblob(cfg) => build_operator(
            init_azblob_operator(cfg)?,
            cfg.network_config.as_ref(),
            endpoint_policy_scope,
        )?,
        StorageParams::Fs(cfg) => {
            build_operator(init_fs_operator(cfg)?, None, endpoint_policy_scope)?
        }
        StorageParams::Gcs(cfg) => build_operator(

View on GitHub (pinned to 288d84d76e)