{"record":{"id":"3be070dd15af8fdb","repo":"risingwavelabs/risingwave","slug":"streaming-job-job-id-not-found","errorCode":null,"errorMessage":"streaming job {job_id} not found","messagePattern":"streaming job (.+?) not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/meta/src/controller/scale.rs","lineNumber":978,"sourceCode":"        )\n        .map_err(|_| {\n            anyhow!(\n                \"entry fragments {:?} have inconsistent parallelism settings\",\n                entries.iter().copied().collect_vec()\n            )\n        })?;\n\n        let (job_id, distribution_type, vnode_count) = Itertools::exactly_one(\n            entry_fragments\n                .iter()\n                .map(|f| (f.job_id, f.distribution_type, f.vnode_count))\n                .dedup(),\n        )\n        .map_err(|_| anyhow!(\"Multiple jobs found in no-shuffle ensemble\"))?;\n\n        let job = job_map\n            .get(&job_id)\n            .ok_or_else(|| anyhow!(\"streaming job {job_id} not found\"))?;\n\n        let database_resource_group = streaming_job_databases\n            .get(&job_id)\n            .and_then(|database_id| database_map.get(database_id))\n            .unwrap()\n            .resource_group\n            .clone();\n\n        let source_entry_fragment = entry_fragments.iter().find(|f| {\n            let mask = f.fragment_type_mask;\n            if mask.contains(FragmentTypeFlag::Source) {\n                assert!(!mask.contains(FragmentTypeFlag::SourceScan))\n            }\n            mask.contains(FragmentTypeFlag::Source) && !mask.contains(FragmentTypeFlag::Dml)\n        });\n\n        let actor_template = EnsembleActorTemplate::render_new(\n            job,","sourceCodeStart":960,"sourceCodeEnd":996,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/meta/src/controller/scale.rs#L960-L996","documentation":"After resolving the ensemble's single job_id, render_actors_with_allocator fetches the StreamingJob model from job_map. If the job_id resolved from the entry fragments is not present in the loaded job map, this error is returned with the job ID.","triggerScenarios":"An ensemble whose fragments carry a job_id that the load stage did not fetch into job_map — e.g. fragments orphaned from a dropped job inside an ensemble, or a load/dedup bug excluding the job from the StreamingJob query.","commonSituations":"Rescale while a job is being dropped (fragments still present); migration leaving stale fragment rows; job IDs in fragments not matching any streaming_jobs entry.","solutions":["Verify the reported job_id exists in the streaming job catalog; if dropped, remove the orphaned fragments or abort the rescale.","Retry after the concurrent DDL completes.","Ensure load_fragment_context fetches jobs for every fragment's job_id (not just a subset).","Restore from meta backup if the job should exist."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"for fid in ensemble.component_ids() {\n    let job_id = fragments[&fid].job_id;\n    assert!(ctx.job_map.contains_key(&job_id), \"job {job_id} of fragment {fid} not loaded\");\n}","typeGuard":"fn job_in_context(ctx: &LoadedFragmentContext, job_id: JobId) -> bool { ctx.job_map.contains_key(&job_id) }","tryCatchPattern":"let Some(job) = ctx.job_map.get(&job_id) else {\n    warn!(\"job {job_id} disappeared mid-rescale; aborting render\");\n    return Err(anyhow!(\"streaming job {job_id} not found\"));\n};","preventionTips":["Block rescale while jobs are being dropped","Cascade-delete fragments with jobs","Re-load the context if any job removal is detected","Audit post-migration catalogs for orphaned fragments"],"tags":["rescale","streaming-job","allocator","metadata"],"backgroundTag":"entity-not-found","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"}