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

  1. Verify the CREATE OR REPLACE pre-check/drop path runs before the conflict match; fix the control flow if it is skipped.
  2. Check for concurrent procedure DDL on the same procedure name and add locking/serialization.
  3. 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

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


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,
                            },
                            &current_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)