risingwavelabs/risingwave · error · MetaError
no fragment connection from source fragment {} to source bac
Error message
no fragment connection from source fragment {} to source backfill fragment {} What it means
During creation of a source backfill (streaming job rewrite), the code looks up a fragment_relation row from source_fragment_id to the source backfill fragment; if none exists it returns 'no fragment connection from source fragment {} to source backfill fragment {}'. The persisted fragment graph lacks the mandatory NoShuffle dispatch edge these fragments must have.
Source
Thrown at src/meta/src/controller/fragment.rs:1747
/// (`backfill_actor_id`, `upstream_source_actor_id`)
pub async fn get_running_actors_for_source_backfill(
&self,
source_backfill_fragment_id: FragmentId,
source_fragment_id: FragmentId,
) -> MetaResult<Vec<(ActorId, ActorId)>> {
let inner = self.inner.read().await;
let txn = inner.db.begin().await?;
let fragment_relation: DispatcherType = FragmentRelation::find()
.select_only()
.column(fragment_relation::Column::DispatcherType)
.filter(fragment_relation::Column::SourceFragmentId.eq(source_fragment_id))
.filter(fragment_relation::Column::TargetFragmentId.eq(source_backfill_fragment_id))
.into_tuple()
.one(&txn)
.await?
.ok_or_else(|| {
anyhow!(
"no fragment connection from source fragment {} to source backfill fragment {}",
source_fragment_id,
source_backfill_fragment_id
)
})?;
if fragment_relation != DispatcherType::NoShuffle {
return Err(anyhow!("expected NoShuffle but got {:?}", fragment_relation).into());
}
let load_fragment_distribution_type = |txn, fragment_id: FragmentId| async move {
let result: MetaResult<DistributionType> = try {
FragmentModel::find_by_id(fragment_id)
.select_only()
.column(fragment::Column::DistributionType)
.into_tuple()
.one(txn)
.awaitView on GitHub (pinned to 6469eb736d)
Solutions
- Check fragment_relation rows for the reported source_fragment_id in the meta DB to see what edges exist
- Verify cluster and table were created with a version supporting source backfill (upgrade if older)
- Retry the operation; if the relation row is genuinely missing, the table's metadata is corrupted and may need recreation
- Contact RisingWave support / file an issue with the job id and fragment ids if stock writes lose the relation
Defensive patterns
Strategy: validation
Validate before calling
let rel = fragment_relation::Entity::find()
.filter(fragment_relation::Column::SourceFragmentId.eq(src))
.filter(fragment_relation::Column::TargetFragmentId.eq(dst))
.one(&db).await?;
if rel.is_none() { return Err(skip_backfill()); } Try / catch
match create_source_backfill(...).await { Err(e) if e.to_string().contains("no fragment connection") => log_corrupt_metadata(job_id), other => other } Prevention
- Keep the cluster on versions whose backfill fragment layout matches the data
- Never hand-edit the meta store
- Verify fragment_relation rows exist after migrations
When it happens
Trigger: Applying a source backfill rewrite for a table whose persisted fragment relations do not contain the expected source→source-backfill edge — e.g. meta data written by an older RisingWave version, partial write of the relation table, or a corrupted/edited meta store.
Common situations: Cluster upgraded across versions where backfill fragment layout changed; source backfill triggered on a table created before a migration; manual meta DB edits; interrupted DDL that wrote fragments without relations.
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
- expected NoShuffle but got {:?}
- failed to find fragment: {}
- sink fragment not found for sink id {}
- Iceberg snapshot {snapshot_id} not found
- topic {} not found
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/38a8594e9d31cdb9.
Report an issue: GitHub.