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
- In the caller, branch on stage_type and use the external storage location directly for StageType::External, never stage_prefix().
- Guard with a stage_type check before calling stage_prefix().
- 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
- Always branch on StageType before building a stage prefix or operator.
- Remember external stages have no /stage/ prefix; use their storage location.
- Verify stage_type is persisted correctly at CREATE STAGE time.
- Add tests that run operator init for every StageType variant.
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
- _ => unreachable!()
- internal error: entered unreachable code
- unexpected InternalColumnType in stage file reader
- partial_cmp failed for non-NaN value
- {}
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)