{"record":{"id":"c47897b8594acac6","repo":"affaan-m/ECC","slug":"configured-harness-runner-for-runner-key-is-miss","errorCode":null,"errorMessage":"Configured harness runner for {runner_key} is missing a program","messagePattern":"Configured harness runner for (.+?) is missing a program","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"ecc2/src/session/manager.rs","lineNumber":2335,"sourceCode":"            session.state\n        );\n    }\n\n    if let Some(worktree) = session.worktree.as_ref() {\n        let _ = crate::worktree::remove(worktree);\n    }\n\n    db.delete_session(&session.id)?;\n    Ok(())\n}\n\nfn agent_program(cfg: &Config, agent_type: &str) -> Result<PathBuf> {\n    let harness = HarnessKind::from_agent_type(agent_type);\n    let runner_key = SessionHarnessInfo::runner_key(agent_type);\n    if let Some(runner) = cfg.harness_runner(&runner_key) {\n        let program = runner.program.trim();\n        if program.is_empty() {\n            anyhow::bail!(\"Configured harness runner for {runner_key} is missing a program\");\n        }\n        return Ok(PathBuf::from(program));\n    }\n\n    match harness {\n        HarnessKind::Claude => Ok(PathBuf::from(\"claude\")),\n        HarnessKind::Codex => Ok(PathBuf::from(\"codex\")),\n        HarnessKind::OpenCode => Ok(PathBuf::from(\"opencode\")),\n        HarnessKind::Gemini => Ok(PathBuf::from(\"gemini\")),\n        other => anyhow::bail!(\"Unsupported agent type: {other}\"),\n    }\n}\n\nfn resolve_session(db: &StateStore, id: &str) -> Result<Session> {\n    let session = if id == \"latest\" {\n        db.get_latest_session()?\n    } else {\n        db.get_session(id)?","sourceCodeStart":2317,"sourceCodeEnd":2353,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/ecc2/src/session/manager.rs#L2317-L2353","documentation":"agent_program resolves the executable for a harness runner. If a custom harness runner is configured for runner_key but its program field is empty (or whitespace-only) after trimming, the library bails instead of silently falling back to the default binary. This catches malformed runner configuration that would otherwise produce a cryptic spawn failure.","triggerScenarios":"cfg.harness_runner(&runner_key) returns Some(runner) whose runner.program.trim() is empty; e.g., config with an entry like [harness_runner.mykey] program = \"\".","commonSituations":"A partially filled config where a user created a runner section but left program blank; template/config generation writing empty strings for program; env var interpolation yielding empty string; copying a config template and forgetting to set program.","solutions":["Set the program field to the executable path (e.g., /usr/local/bin/claude) in the harness runner config","Remove the runner config entry entirely so the library falls back to the built-in default (claude/codex/opencode/gemini)","Validate the runner config at startup: trim and check non-empty program for every configured runner","Ensure env-var interpolation used for program is not resolving to an empty string"],"exampleFix":"# before\ncfg:\n  harness_runner:\n    claude-pro:\n      program: \"\"\n# after\ncfg:\n  harness_runner:\n    claude-pro:\n      program: \"/usr/local/bin/claude\"","handlingStrategy":"validation","validationCode":"fn validate_runner_config(cfg: &Config) -> Result<(), String> {\n    for (key, runner) in cfg.all_harness_runners() {\n        if runner.program.trim().is_empty() {\n            return Err(format!(\"harness runner '{key}' has empty program\"));\n        }\n    }\n    Ok(())\n}","typeGuard":"fn has_program(r: &HarnessRunner) -> bool { !r.program.trim().is_empty() }","tryCatchPattern":"match launch(...) {\n    Err(e) if e.to_string().contains(\"is missing a program\") => {\n        eprintln!(\"fix harness_runner config: set a non-empty program or remove the entry\");\n        Err(e)\n    }\n    other => other,\n}","preventionTips":["Validate runner configs at startup before launching sessions","Never write empty program values; omit the entry to use defaults","Check env-var interpolation doesn't produce empty program strings"],"tags":["config","harness","runner","validation"],"backgroundTag":"empty-required-field","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}