Hmbown/CodeWhale · error · anyhow::Error
doctor configuration validation failed; see JSON output
Error message
doctor configuration validation failed; see JSON output
What it means
`codewhale doctor` validates the loaded configuration before reporting; when validation fails it prints a redacted JSON error object to stdout and then bails with this deliberately generic stderr line. The split is intentional: configuration errors can contain credential material, so the sanitized detail (safe_message) only ever reaches stdout, and Rust's Result termination path stays secret-free.
Source
Thrown at crates/tui/src/lib.rs:6551
/// Emit a bounded, secret-redacted JSON failure when configuration cannot be
/// loaded or validated. Invalid configuration must not be forced through the
/// normal doctor report because its route/capability facts would be misleading.
fn run_doctor_json_config_error(error: &anyhow::Error) -> Result<()> {
let safe_message = error
.downcast_ref::<crate::config::SafeConfigDiagnostic>()
.map(ToString::to_string);
let report = serde_json::json!({
"status": "error",
"error": {
"kind": "config_validation",
"message": safe_message.as_deref().unwrap_or("configuration validation failed; details omitted because configuration errors may contain credential material"),
},
});
println!("{}", serde_json::to_string_pretty(&report)?);
// Keep stderr generic: the actionable, redacted error is already on
// stdout, and Rust's Result termination must never redisclose a secret.
bail!("doctor configuration validation failed; see JSON output")
}
/// Machine-readable counterpart to `run_doctor`. This report is always
/// structural and offline; live probe flags conflict with `--json`.
fn run_doctor_json(
config: &Config,
workspace: &Path,
config_path_override: Option<&Path>,
plugins: &crate::plugins::PluginRegistry,
) -> Result<()> {
use serde_json::json;
let doctor_paths = crate::doctor::DoctorPathReport::resolve(config_path_override)?;
let config_path = &doctor_paths.config;
let secret_backend = codewhale_secrets::diagnose_secret_backend();
let credential = resolve_credential_diagnostic(config);
View on GitHub (pinned to 0c42157ee5)
Solutions
- Re-run `codewhale doctor` and read `error.message` from the stdout JSON — that is where the redacted specifics live
- Fix the config key the message names, in the config file doctor loaded
- Pre-validate that the file parses (any TOML linter) and re-run doctor
- If redaction hides the cause, temporarily remove the secret from config and re-run to surface the underlying error
Example fix
// before: stderr only shows the generic line $ codewhale doctor 2>&1 >/dev/null doctor configuration validation failed; see JSON output // after: pull the actionable, redacted message from stdout $ codewhale doctor 2>/dev/null | jq -r '.error.message'
Defensive patterns
Strategy: try-catch
Validate before calling
// preflight: parse the config file before invoking doctor let raw = std::fs::read_to_string(&config_path)?; toml::from_str::<toml::Value>(&raw)?; // surfaces the real syntax error here
Try / catch
out=$(codewhale doctor 2>/dev/null); rc=$? if [ "$rc" -ne 0 ]; then msg=$(printf '%s' "$out" | jq -r '.error.message // "unknown"') echo "doctor config validation failed: $msg" >&2 fi
Prevention
- Never store credentials directly in config.toml; use the key store so validation errors stay descriptive
- Re-run doctor after every config edit or version upgrade
- Script against the stdout JSON, not stderr, when doctor fails
When it happens
Trigger: run_doctor reaches config validation and it returns Err: malformed TOML, an invalid route/provider setting, or an unreadable config file (including the config_path_override path). The stdout JSON carries kind "config_validation".
Common situations: Hand-edited config.toml with a typo; a codewhale upgrade changed the config schema; conflicting env overrides; a credential embedded in a provider URL that validation rejects.
Understand the failure class
Background: Config validation failed: what "invalid value for {key}" and settings-rejection errors mean across 19 open-source libraries — this error's family across 19 libraries.
Related errors
- Model name cannot be empty
- provider auth source command must include at least one non-e
- provider auth source secret must include secret_id
- context_window must be greater than 0
- custom provider '{provider_id}' must set [providers.{provide
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/09e4a79cdb3b6f18.
Report an issue: GitHub.