risingwavelabs/risingwave · error
the source object store does not appear to be legacy: {} ver
Error message
the source object store does not appear to be legacy: {} versus {} What it means
While listing objects under source_dir, the tool derives the expected legacy path for each object and compares it with the actual key. A mismatch means the store contains objects that do not match the legacy naming scheme, so a mechanical migration would be unsafe.
Source
Thrown at src/ctl/src/cmd_impl/hummock/migrate_legacy_object.rs:86
{
let legacy_path = object.key;
assert_eq!(
&legacy_path[..source_dir.len()],
source_dir,
"{legacy_path} versus {source_dir}"
);
if legacy_path.ends_with('/') {
tracing::warn!(legacy_path, "skip directory");
continue;
}
let new_path = format!("{}{}", target_dir, &legacy_path[source_dir.len()..]);
from_to.push((legacy_path, new_path));
} else {
let object_id = get_object_id_from_path(&object.key);
let legacy_prefix = get_object_prefix(object_id.as_raw().as_raw_id(), false);
let legacy_path = get_object_data_path(&legacy_prefix, source_dir, object_id);
if object.key != legacy_path {
return Err(anyhow!(format!(
"the source object store does not appear to be legacy: {} versus {}",
object.key, legacy_path
)));
}
let new_path = get_object_data_path(
&get_object_prefix(object_id.as_raw().as_raw_id(), true),
target_dir,
object_id,
);
from_to.push((legacy_path, new_path));
}
count += 1;
if from_to.len() >= concurrency as usize {
copy(std::mem::take(&mut from_to).into_iter(), opendal.inner()).await?;
}
}
if !from_to.is_empty() {
copy(from_to.into_iter(), opendal.inner()).await?;View on GitHub (pinned to 6469eb736d)
Solutions
- Inspect the two reported paths to identify the offending object and remove/move it if it does not belong
- Resume a partial migration from where it stopped instead of re-listing mixed content
- Ensure source_dir points only at the legacy object directory
- Verify which prefix strategy (new vs legacy) the objects actually use before migrating
Example fix
null
Defensive patterns
Strategy: validation
Validate before calling
let expected = get_object_data_path(&get_object_prefix(id.as_raw().as_raw_id(), false), source_dir, &object_id);
if listed_key != expected {
eprintln!("non-legacy object found: {} (expected {})", listed_key, expected);
} Prevention
- Run migration exactly once and track completion state
- Point source_dir at a directory containing only legacy objects
- Inspect listing output for unexpected keys before converting
When it happens
Trigger: The listed object's key equals neither the new-prefix path nor the recomputed legacy path — e.g. partially migrated store, hand-copied objects, or objects from a different prefix scheme inside source_dir.
Common situations: Re-running migration after a partial run; mixing old/new object prefixes in one directory; pointing source_dir at a directory containing unrelated objects.
Related errors
- the source_dir and target_dir must not be empty
- the target_dir must not include source_dir
- Storage error: {0}
- Invalid value `{value}` for `{entry}`
- unrecognized configs: {:?}
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/8e26e5ed73b73a99.
Report an issue: GitHub.