databendlabs/databend · error

stage_prefix should never be called on external stage, must…

Error message

stage_prefix should never be called on external stage, must be a bug

What it means

UserStage::stage_prefix builds a filesystem-style prefix (/stage/...) for internal/user stages. For StageType::External it deliberately panics with unreachable!(), because an external stage's location lives outside the service and has no such prefix; calling it there is documented as a bug. The caller init_stage_operator is expected to route external stages to a different code path.

Solutions

  1. In the caller, branch on stage_type and use the external storage location directly for StageType::External, never stage_prefix().
  2. Guard with a stage_type check before calling stage_prefix().
  3. If the stage should be internal, fix how the stage was created (CREATE STAGE vs external location) so stage_type is correct.

Example fix

// before
let prefix = stage.stage_prefix();
// after
if stage.stage_type == StageType::External {
    let prefix = stage.external_location_prefix();
} else {
    let prefix = stage.stage_prefix();
}
Defensive patterns

Strategy: validation

Validate before calling

if stage.stage_type == StageType::External {
    // use external location instead of stage_prefix()
}

Try / catch

match stage.stage_type {
    StageType::External => init_external_operator(stage)?,
    _ => init_internal_operator_with_prefix(stage, stage.stage_prefix()),
}

Prevention

When it happens

Trigger: Calling stage_prefix() on a stage whose stage_type is StageType::External — e.g. init_stage_operator (or new code) failing to check stage_type before computing a prefix for an external/object-storage stage.

Common situations: Creating an operator for a user-created external stage pointing at object storage; refactors that unified internal and external stage handling but forgot the external branch; stages persisted with the wrong stage_type.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at src/meta/app/src/principal/user_stage.rs:516

    }

    pub fn with_allow_credential_chain(mut self, allow: bool) -> StageInfo {
        self.allow_credential_chain = allow;
        self
    }

    /// Get the prefix of stage.
    ///
    /// Use this function to get the prefix of this stage in the data operator.
    ///
    /// # Notes
    ///
    /// This function should never be called on external stage because it's meanless. Something must be wrong.
    pub fn stage_prefix(&self) -> String {
        match self.stage_type {
            StageType::LegacyInternal => format!("/stage/{}/", self.stage_name),
            StageType::External => {
                unreachable!("stage_prefix should never be called on external stage, must be a bug")
            }
            StageType::Internal => format!("/stage/internal/{}/", self.stage_name),
            StageType::User => format!("/stage/user/{}/", self.stage_name),
        }
    }
}

#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct StageFile {
    pub path: String,
    pub size: u64,
    pub md5: Option<String>,
    pub last_modified: DateTime<Utc>,
    pub creator: Option<UserIdentity>,
    pub etag: Option<String>,
}

View on GitHub (pinned to 288d84d76e)