risingwavelabs/risingwave · error
the source_dir and target_dir must not be empty
Error message
the source_dir and target_dir must not be empty
What it means
The legacy object migration command trims trailing slashes from source_dir/target_dir and rejects either being empty, because migrating to or from the bucket root is not supported by the path-relative rewrite logic. It fails fast before touching the object store.
Source
Thrown at src/ctl/src/cmd_impl/hummock/migrate_legacy_object.rs:41
};
use risingwave_object_store::object::object_metrics::ObjectStoreMetrics;
use risingwave_object_store::object::prefix::opendal_engine::get_object_prefix;
use risingwave_object_store::object::{
ObjectStoreImpl, OpendalObjectStore, build_remote_object_store,
};
pub async fn migrate_legacy_object(
url: String,
source_dir: String,
target_dir: String,
concurrency: u32,
) -> anyhow::Result<()> {
let source_dir = source_dir.trim_end_matches('/');
let target_dir = target_dir.trim_end_matches('/');
println!("Normalized source_dir: {source_dir}.");
println!("Normalized target_dir: {target_dir}.");
if source_dir.is_empty() || target_dir.is_empty() {
return Err(anyhow!("the source_dir and target_dir must not be empty"));
}
if target_dir.starts_with(source_dir) {
return Err(anyhow!("the target_dir must not include source_dir"));
}
let mut config = ObjectStoreConfig::default();
config.s3.developer.use_opendal = true;
let store = build_remote_object_store(
&url,
ObjectStoreMetrics::unused().into(),
"migrate_legacy_object",
config.into(),
)
.await;
let ObjectStoreImpl::Opendal(opendal) = store else {
return Err(anyhow!("OpenDAL is required"));
};
let mut iter = opendal.list(source_dir, None, None).await?;
let mut count = 0;View on GitHub (pinned to 6469eb736d)
Solutions
- Pass explicit non-empty relative directory prefixes for both source_dir and target_dir
- If you truly need whole-bucket migration, restructure so objects live under a common prefix
- Check shell quoting/variable expansion isn't producing an empty argument
Example fix
// before rw hummock migrate-legacy-object --source-dir '' --target-dir 'new/' // after rw hummock migrate-legacy-object --source-dir 'legacy' --target-dir 'new'
Defensive patterns
Strategy: validation
Validate before calling
let s = source_dir.trim_end_matches('/');
let t = target_dir.trim_end_matches('/');
if s.is_empty() || t.is_empty() {
panic!("source_dir and target_dir must be non-empty (not '/')");
} Prevention
- Always pass explicit relative prefixes, never '/' or empty strings
- Default script variables to real values, not empty strings
- Echo the normalized dirs before running migration
When it happens
Trigger: Running `rw hummock migrate-legacy-object` with an empty or '/'-only source_dir or target_dir argument.
Common situations: Omitting the --source-dir/--target-dir flags entirely; passing '/' intending 'whole bucket'; script variables defaulting to empty strings.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- the target_dir must not include source_dir
- the source object store does not appear to be legacy: {} ver
- OpenDAL is required
- Storage error: {0}
- Invalid value `{value}` for `{entry}`
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/432a2eea6d01de04.
Report an issue: GitHub.