risingwavelabs/risingwave · error · MetaError

job {} not found in database

Error message

job {} not found in database

What it means

get_job_fragments_by_id looks up the streaming job row by primary key in the meta database. If no row exists for `job_id`, it returns an anyhow error 'job {} not found in database', meaning the requested job id does not correspond to any persisted streaming job.

Source

Thrown at src/meta/src/controller/fragment.rs:651

        &self,
        job_id: JobId,
    ) -> MetaResult<(
        StreamJobFragments,
        HashMap<FragmentId, Vec<StreamActor>>,
        HashMap<ActorId, PbActorStatus>,
    )> {
        let inner = self.inner.read().await;

        // Load fragments matching the job from the database
        let fragments: Vec<_> = FragmentModel::find()
            .filter(fragment::Column::JobId.eq(job_id))
            .all(&inner.db)
            .await?;

        let job_info = StreamingJob::find_by_id(job_id)
            .one(&inner.db)
            .await?
            .ok_or_else(|| anyhow::anyhow!("job {} not found in database", job_id))?;

        let fragment_actors =
            self.collect_fragment_actor_pairs(fragments, job_info.stream_context())?;

        let job_definition = resolve_streaming_job_definition(&inner.db, &HashSet::from([job_id]))
            .await?
            .remove(&job_id);

        Self::compose_table_fragments(
            job_id,
            job_info.job_status.into(),
            job_info.stream_context(),
            fragment_actors,
            job_info.max_parallelism as _,
            job_definition,
        )
    }

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Confirm the job exists: SELECT ... FROM streaming_job WHERE job_id = <id> in the meta DB, or SHOW MATERIALIZED VIEWS
  2. Refresh any cached job id in the client and re-resolve the job by name
  3. Handle the not-found error gracefully on the caller side (e.g. return a 404-equivalent rather than surfacing it as an internal error)
  4. If the job should exist, check meta node logs for a drop job around the failure time

Example fix

// before
let job = StreamingJob::find_by_id(job_id).one(&inner.db).await?.ok_or_else(|| anyhow!("job {} not found", job_id))?;
// after
match StreamingJob::find_by_id(job_id).one(&inner.db).await? {
    Some(job) => job,
    None => return Err(MetaError::catalog(JobNotFound::new(job_id).into())),
}
Defensive patterns

Strategy: validation

Validate before calling

let exists = StreamingJob::find_by_id(job_id).one(&db).await?.is_some();
if !exists { return Err(not_found()); }

Try / catch

match get_job_fragments_by_id(job_id).await { Ok(f) => f, Err(e) if e.to_string().contains("not found in database") => handle_job_gone(job_id), Err(e) => return Err(e) }

Prevention

When it happens

Trigger: Calling FragmentManager::get_job_fragments_by_id with a job_id that was already dropped, never created, or a table/system id that is not a streaming job row.

Common situations: Race between a client fetching job fragments and a DROP MATERIALIZED VIEW completing; stale job id cached in the frontend after the job was removed; using a table id from another environment's meta store.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/485aab13311ae615. Report an issue: GitHub.