neondatabase/neon · error

could not parse config file: {}

Error message

could not parse config file: {}

What it means

On the test-only configuration path, compute_ctl tried to serde-parse the file at params.config_path_test_only as a ComputeConfig JSON document and serde failed. The error chain includes the serde message with line/column. Production always takes the control-plane path instead; this fires only when config_path_test_only is explicitly set.

Source

Thrown at compute_tools/src/configurator.rs:81

            // Drop the lock guard here to avoid holding the lock while downloading config from the control plane / HCC.
            // This is the only thread that can move compute_ctl out of the `RefreshConfiguration` state, so it
            // is safe to drop the lock like this.
            drop(state);

            let get_config_result: anyhow::Result<ComputeConfig> =
                if let Some(config_path) = &compute.params.config_path_test_only {
                    // This path is only to make testing easier. In production we always get the config from the HCC.
                    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"))
                };

View on GitHub (pinned to 8f60b04da4)

Solutions

  1. Validate the file is well-formed JSON first (jq . config.json)
  2. Diff the document against the ComputeConfig serde schema of the compute_ctl build you run (fields, nesting, types)
  3. Regenerate the config file from a known-good source or copy an example from the repo's test fixtures
  4. Keep humans out of the loop: write the file atomically from tooling to avoid truncation

Example fix

// before
let path = Path::new(config_path);
if let Ok(file) = File::open(path) { serde_json::from_reader::<File, ComputeConfig>(file) ... }
// after: surface serde position instead of a generic re-wrap
match serde_json::from_reader::<File, ComputeConfig>(file) {
    Ok(config) => Ok(config),
    Err(e) => Err(anyhow!("could not parse config file at {}: {e}", config_path.display())),
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate before compute_ctl reads it
let raw = std::fs::read_to_string(path)?;
serde_json::from_str::<ComputeConfig>(&raw)
    .map_err(|e| anyhow!("config at {path} is not a valid ComputeConfig: {e}"))?;

Type guard

fn is_parseable_compute_config(path: &Path) -> bool {
    std::fs::File::open(path).ok()
        .and_then(|f| serde_json::from_reader::<_, ComputeConfig>(f).ok())
        .is_some()
}

Prevention

When it happens

Trigger: configurator runs with --config-path-test-only (or equivalent param) pointing at a file that is valid enough to open but is not parseable as ComputeConfig: malformed JSON, wrong field types, unknown/renamed required fields.

Common situations: Hand-edited config.json with trailing commas or comments (not valid JSON); schema drift after upgrading compute_ctl (fields renamed/typed differently); pointing the flag at a ComputeSpec file instead of a ComputeConfig wrapper; file truncated mid-write.

Related errors


AI-assisted analysis of neondatabase/neon@8f60b04da4 (2026-08-16). Data as JSON: /api/errors/99c6c482b5d4add9. Report an issue: GitHub.