databendlabs/databend · error
raft_dir of meta service must be an absolute path, but got
Error message
raft_dir of meta service must be an absolute path, but got: {:?} What it means
`load_meta_config` validates that the meta service's `raft_config.raft_dir` is an absolute path (starts with `/`) and returns this error when it is not. The restore path needs to locate the raft data directory directly, so a relative path would resolve against an unpredictable working directory.
Solutions
- Edit the meta config file and set `raft_config.raft_dir` to an absolute path (e.g. `/var/lib/databend/meta`).
- Verify the directory actually exists and contains the raft data before restoring.
- If the config is generated by a script, make the script emit absolute paths.
- Re-run restore after fixing the path.
Example fix
// before (meta config toml) [raft_config] raft_dir = "./meta_data" // after [raft_config] raft_dir = "/var/lib/databend/meta_data"
Defensive patterns
Strategy: validation
Validate before calling
let dir = cfg["raft_config"]["raft_dir"].as_str().unwrap();
if !dir.starts_with('/') {
return Err(format!("raft_dir must be absolute, got: {dir}"));
}
if !std::path::Path::new(dir).is_dir() {
return Err(format!("raft_dir does not exist: {dir}"));
} Type guard
fn is_absolute_existing_dir(p: &str) -> bool {
p.starts_with('/') && std::path::Path::new(p).is_dir()
} Try / catch
match bendsave::load_meta_config(path) {
Ok(cfg) => cfg,
Err(e) if e.to_string().contains("raft_dir") => {
eprintln!("fix raft_dir in {path}: {e}");
std::process::exit(2);
}
Err(e) => return Err(e.into()),
} Prevention
- Always use absolute paths for raft_dir in meta configs
- Have config generators resolve paths with realpath/canonicalization
- Check the directory exists and is readable before running restore
- Document the absolute-path requirement in config templates
When it happens
Trigger: Calling `load_meta_config` (directly or via `restore`) with a meta config whose `[raft_config] raft_dir` value is relative, e.g. `"./meta"` or `"meta_data"`.
Common situations: Hand-written or copied meta configs using relative paths; configs generated for environments where the meta process was launched from a fixed working directory so a relative path happened to work there.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- grpc_api_address MUST not be empty!
- remove_percent MUST in [0, 100)!
- {msg}
- bendsave requires bucket but it's empty in uri
- node id ( ) has to be one of cluster member( )
AI-assisted analysis of databendlabs/databend@288d84d76e (2026-09-11).
Data as JSON: /api/errors/9a511a571964b93f.
Report an issue: GitHub.
Appendix: source
Thrown at src/bendsave/src/storage.rs:85
pub fn load_query_storage(cfg: &InnerConfig) -> Result<Operator> {
let op = init_operator(&cfg.storage.params)?;
debug!("databend storage loaded: {:?}", op.info());
Ok(op)
}
/// Load the configuration file of databend meta.
///
/// The given input is the path to databend meta's configuration file.
pub fn load_meta_config(path: &str) -> Result<MetaServiceConfig> {
let content = std::fs::read_to_string(path)?;
let outer_config: databend_meta_cli_config::Config = toml::from_str(&content)?;
let meta_config: MetaConfig = outer_config
.try_into()
.map_err(|msg: String| anyhow!("{msg}"))?;
let service_config = meta_config.service;
if !service_config.raft_config.raft_dir.starts_with("/") {
return Err(anyhow!(
"raft_dir of meta service must be an absolute path, but got: {:?}",
service_config.raft_config.raft_dir
));
}
debug!("databend meta storage loaded: {:?}", service_config);
Ok(service_config)
}
/// Init databend query instance so that we can read meta and check license
/// for it.
///
/// FIXME: I really don't like this pattern, but it's how databend work.
pub fn init_query(cfg: &InnerConfig) -> Result<()> {
GlobalInstance::init_production();
GlobalConfig::init(cfg, &BUILD_INFO)?;
GlobalIORuntime::init(cfg.storage.num_cpus as usize)?;View on GitHub (pinned to 288d84d76e)