{"record":{"id":"8188ae4b89848126","repo":"risingwavelabs/risingwave","slug":"obj-has-no-database-id","errorCode":null,"errorMessage":"obj has no database id: {:?}","messagePattern":"obj has no database id: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/meta/src/controller/streaming_job.rs","lineNumber":1045,"sourceCode":"        let mut inner = self.inner.write().await;\n        let txn = inner.db.begin().await?;\n\n        let obj = Object::find_by_id(job_id).one(&txn).await?;\n        let Some(obj) = obj else {\n            tracing::warn!(\n                id = %job_id,\n                \"streaming job not found when aborting creating, might be cancelled already or cleaned by recovery\"\n            );\n            return Ok(AbortCreatingJobResult {\n                aborted: true,\n                database_id: None,\n                aborted_sink_ids: vec![],\n                cancel_info: None,\n            });\n        };\n        let database_id = obj\n            .database_id\n            .ok_or_else(|| anyhow!(\"obj has no database id: {:?}\", obj))?;\n        let streaming_job = streaming_job::Entity::find_by_id(job_id).one(&txn).await?;\n\n        if let Some(streaming_job) = &streaming_job {\n            if streaming_job.job_status == JobStatus::Created {\n                tracing::warn!(%job_id, \"streaming job is already created, ignore abort request\");\n                return Ok(AbortCreatingJobResult {\n                    aborted: false,\n                    database_id: Some(database_id),\n                    aborted_sink_ids: vec![],\n                    cancel_info: None,\n                });\n            }\n\n            if !is_cancelled && streaming_job.job_status == JobStatus::Creating {\n                if (obj.obj_type == ObjectType::Table || obj.obj_type == ObjectType::Sink)\n                    && check_if_belongs_to_iceberg_table(&txn, job_id).await?\n                {\n                    // If the job belongs to an Iceberg table, we still need to clean it.","sourceCodeStart":1027,"sourceCodeEnd":1063,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/meta/src/controller/streaming_job.rs#L1027-L1063","documentation":"When aborting a creating streaming job, the object row associated with the job has no database_id set, which is required for cleanup. This is an internal invariant violation: every streaming job object must record its database.","triggerScenarios":"Calling try_abort_creating_streaming_job for a job whose Object model row has database_id = None.","commonSituations":"Corrupted metadata after partial write/failed migration, manual metadata-store edits, or bugs in object creation.","solutions":["Inspect the object row for the job in the metadata store; this is data corruption, not user-fixable via SQL.","Restore the meta store from backup.","Drop the orphaned object/job records manually if recovery is acceptable.","File a bug with the job_id from the message."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"fn has_database_id(obj: &Object) -> Option<DatabaseId> { obj.database_id }","tryCatchPattern":"match catalog.try_abort_creating_streaming_job(job_id).await {\n    Err(e) if e.to_string().contains(\"obj has no database id\") => /* meta-store corruption: restore from backup; do not retry */,\n    other => other?,\n}","preventionTips":["Never hand-edit the meta store","Take meta backups before migrations","Alert on object rows missing database_id"],"tags":["meta","catalog","invariant"],"backgroundTag":"internal-invariant-violation","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}