neondatabase/neon · error
could not open config file at path: {}
Error message
could not open config file at path: {} What it means
The test-only config loader could not even open the file at params.config_path_test_only: File::open failed (usually ENOENT - no such file, or EACCES - permission denied inside the container). Distinguished from error 13, which is opened-but-unparseable. Only reachable when config_path_test_only is set; production fetches config from the control plane.
Source
Thrown at compute_tools/src/configurator.rs:89
info!(
"reloading config.json from path: {}",
config_path.to_string_lossy()
);
let path = Path::new(config_path);
if let Ok(file) = File::open(path) {
match serde_json::from_reader::<File, ComputeConfig>(file) {
Ok(config) => Ok(config),
Err(e) => {
error!("could not parse config file: {}", e);
Err(anyhow::anyhow!("could not parse config file: {}", e))
}
}
} else {
error!(
"could not open config file at path: {:?}",
config_path.to_string_lossy()
);
Err(anyhow::anyhow!(
"could not open config file at path: {}",
config_path.to_string_lossy()
))
}
} else if let Some(control_plane_uri) = &compute.params.control_plane_uri {
get_config_from_control_plane(control_plane_uri, &compute.params.compute_id)
} else {
Err(anyhow::anyhow!("config_path_test_only is not set"))
};
// Parse any received ComputeSpec and transpose the result into a Result<Option<ParsedSpec>>.
let parsed_spec_result: Result<Option<ParsedSpec>> =
get_config_result.and_then(|config| {
if let Some(spec) = config.spec {
if let Ok(pspec) = ParsedSpec::try_from(spec) {
Ok(Some(pspec))
} else {
Err(anyhow::anyhow!("could not parse spec"))View on GitHub (pinned to 8f60b04da4)
Solutions
- Verify the exact path exists from inside the same container/user: ls -l <path>
- Use an absolute path; check volume mounts and their subPaths if running in K8s
- chmod/chown the file so the runtime user can read it
- Confirm you actually meant the test path; in production you want control_plane_uri instead
Example fix
# before: relative or wrong path -> could not open config file --config-path-test-only config.json # after --config-path-test-only /etc/neon/config.json # mounted, readable, absolute
Defensive patterns
Strategy: validation
Validate before calling
// Pre-flight the test config path before startup
let p = std::path::Path::new(&config_path);
if !p.is_file() { anyhow::bail!("config file {p:?} does not exist"); }
if !p.metadata()?.permissions().readonly() { /* at least readable check */ } Type guard
fn config_file_readable(path: &Path) -> bool {
path.is_file() && std::fs::File::open(path).is_ok()
} Prevention
- Always pass absolute paths for --config-path-test-only
- Smoke-test container mounts: assert the file exists in the entrypoint before exec'ing compute_ctl
- Run compute_ctl as the same user that owns the config file, or chmod 0644
When it happens
Trigger: compute_ctl started with a config path that does not exist in the container (wrong volume mount, relative path resolved against an unexpected cwd), or a file with permissions the runtime user cannot read.
Common situations: Docker/K8s volume not mounted at the expected path; typo in the --config-path-test-only value; path from a host build leaked into the container; file owned by root with 0600 while compute_ctl runs as non-root; CI checkout layout changed.
Related errors
- could not parse config file: {}
- connection to postgres closed
- pageserver connection information should be provided
- safekeeper connstrings should be provided
- tenant id should be provided
AI-assisted analysis of neondatabase/neon@8f60b04da4 (2026-08-16).
Data as JSON: /api/errors/5c716c04c84e1c1e.
Report an issue: GitHub.