risingwavelabs/risingwave · error
catalog object {} has no database
Error message
catalog object {} has no database What it means
alter_schema (moving a catalog object to a new schema) requires the object to belong to a database. If the loaded catalog object has `database_id == None` — a state that should be impossible for movable objects — it errors with `catalog object <id> has no database` instead of proceeding, protecting against corrupt or inconsistent catalog rows.
Source
Thrown at src/meta/src/controller/catalog/alter_op.rs:664
}
if object_type == ObjectType::Table {
let table_type = Table::find_by_id(object_id.as_table_id())
.select_only()
.column(table::Column::TableType)
.into_tuple::<TableType>()
.one(&txn)
.await?
.ok_or_else(|| MetaError::catalog_id_not_found("table", object_id))?;
if table_type == TableType::Internal {
return Err(MetaError::catalog_id_not_found("table", object_id));
}
}
if obj.schema_id == Some(new_schema) {
return Ok(IGNORED_NOTIFICATION_VERSION);
}
let database_id = obj
.database_id
.ok_or_else(|| anyhow!("catalog object {} has no database", object_id))?;
// Indexes are named schema objects rather than objects belonging to their primary table.
// Move them with a table explicitly, while subscriptions remain in their own schemas.
let mut objects = vec![obj];
if object_type == ObjectType::Table {
let index_ids = Index::find()
.select_only()
.column(index::Column::IndexId)
.filter(index::Column::PrimaryTableId.eq(object_id.as_table_id()))
.into_tuple::<IndexId>()
.all(&txn)
.await?;
objects.extend(
Object::find()
.filter(
object::Column::Oid
.is_in(index_ids.into_iter().map(|id| id.as_object_id())),
)View on GitHub (pinned to 6469eb736d)
Solutions
- Identify the object id from the message and inspect the catalog to see why its database_id is NULL.
- Re-create the affected object with the correct schema/database and drop the broken one.
- If metadata is corrupt after an upgrade or crash, restore from backup or use clean-data plus re-run DDL.
- Report a bug if a normally database-scoped object (table/view/sink) hit this — it indicates an internal invariant violation.
Example fix
// before: moving an object that may lack a database scope ALTER TABLE mystery_object SET SCHEMA new_schema; // after: verify the object kind and scope first -- only database-scoped objects (tables, views, sinks) support SET SCHEMA SELECT object_id, database_id FROM catalog WHERE object_id = <id>; -- database_id must be non-null
Defensive patterns
Strategy: validation
Validate before calling
-- only database-scoped objects can be moved between schemas SELECT object_id, object_type, database_id FROM catalog WHERE object_id = <id>; -- require database_id IS NOT NULL before ALTER ... SET SCHEMA
Type guard
fn movable_object(obj: &CatalogObject) -> Result<DatabaseId> {
obj.database_id
.ok_or_else(|| anyhow!("object {} is not database-scoped", obj.id))
} Try / catch
match err {
e if e.to_string().contains("has no database") => {
// recreate the object under the target schema; do not retry the ALTER
}
e => return Err(e.into()),
} Prevention
- Only issue SET SCHEMA on tables/views/sinks/indexes, not on non-database-scoped object kinds.
- After failed upgrades, validate catalog integrity before DDL.
- Never hand-edit catalog tables; use supported DDL so database links stay consistent.
When it happens
Trigger: Executing `ALTER ... SET SCHEMA` (alter_schema) on an object whose catalog row lacks a database_id — e.g. an object type that is not database-scoped, or corrupted/inconsistent metadata where the database link was lost.
Common situations: Metadata corruption after a failed upgrade or manual catalog edits; attempting schema moves on object kinds that were never assigned a database; bugs in connector/subscription object creation leaving the database link unset.
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
- obj has no database id: {:?}
- batch refresh job {} has no snapshot backfill info
- recovered snapshot backfill job {} has no snapshot backfill
- database {} not found when resolving reschedule intent
- cannot find subscription with id {}
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/d3b613e61290f086.
Report an issue: GitHub.