databendlabs/databend · error
create_procedure: CreateOrReplace should never conflict…
Error message
create_procedure: CreateOrReplace should never conflict with existent
What it means
The create_procedure interpreter handles 'procedure already exists' conflicts only for plain CREATE. CREATE OR REPLACE is supposed to be resolved earlier by dropping and recreating the procedure, so if the conflict check is ever reached with a CreateOrReplace option the code panics via unreachable!, treating it as an impossible state.
Solutions
- Verify the CREATE OR REPLACE pre-check/drop path runs before the conflict match; fix the control flow if it is skipped.
- Check for concurrent procedure DDL on the same procedure name and add locking/serialization.
- As a user workaround, use CREATE PROCEDURE IF NOT EXISTS or explicitly DROP PROCEDURE before CREATE.
Example fix
// before
CreateOption::CreateOrReplace => {
unreachable!("create_procedure: CreateOrReplace should never conflict with existent");
}
// after
CreateOption::CreateOrReplace => {
// replace path failed to pre-drop; fall back to dropping now
self.drop_if_exists().await?;
self.create_new().await
} Defensive patterns
Strategy: validation
Validate before calling
-- Avoid relying on OR REPLACE conflict paths: check existence first SHOW PROCEDURES LIKE 'my_proc'; -- or use IF NOT EXISTS CREATE PROCEDURE IF NOT EXISTS my_proc() ...;
Try / catch
match res {
Err(e) if e.message().contains("CreateOrReplace should never conflict") => {
// internal regression: fall back to DROP + CREATE
}
other => other?,
} Prevention
- Serialize concurrent DDL on the same procedure name
- Test CREATE OR REPLACE PROCEDURE against existing procedures in CI
- Use DROP + CREATE explicitly instead of OR REPLACE if it misbehaves
When it happens
Trigger: Calling CREATE OR REPLACE PROCEDURE where the early replace path did not take effect and the interpreter still falls into the 'already exists' conflict branch with CreateOption::CreateOrReplace.
Common situations: A regression in the pre-conflict resolution logic for CREATE OR REPLACE PROCEDURE; concurrent create/replace racing so both hit the existence-check branch.
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
- internal error: entered unreachable code
- plan in InsertInputSource::Stag must be CopyIntoTable
- replace with streaming not supported yet
- Input plan must be Query, but it's
- Input plan must be Query, but it's
AI-assisted analysis of databendlabs/databend@288d84d76e (2026-09-11).
Data as JSON: /api/errors/2a43f5a833e53f15.
Report an issue: GitHub.
Appendix: source
Thrown at src/query/service/src/interpreters/interpreter_procedure_create.rs:95
.grant_ownership(
&OwnershipObject::Procedure {
procedure_id: reply.procedure_id,
},
¤t_role.name,
)
.await?;
RoleCacheManager::instance().invalidate_cache(&tenant);
}
Ok(PipelineBuildResult::create())
}
Err(_exist_error) => match self.plan.create_option {
CreateOption::Create => Err(ErrorCode::ProcedureAlreadyExists(format!(
"Procedure '{}' already exists",
self.plan.name.procedure_name()
))),
CreateOption::CreateIfNotExists => Ok(PipelineBuildResult::create()),
CreateOption::CreateOrReplace => {
unreachable!(
"create_procedure: CreateOrReplace should never conflict with existent"
);
}
},
}
}
}
View on GitHub (pinned to 288d84d76e)