{"record":{"id":"4ae1e2e6c754c67e","repo":"zeroclaw-labs/zeroclaw","slug":"update-check-failed","errorCode":null,"errorMessage":"update --check failed: {}","messagePattern":"update --check failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/zeroclaw-gateway/src/version.rs","lineNumber":218,"sourceCode":"}\n\nasync fn run_cli_check(version: Option<&str>) -> anyhow::Result<CliCheck> {\n    let exe = std::env::current_exe().context(\"cannot determine current executable path\")?;\n    let mut cmd = tokio::process::Command::new(exe);\n    cmd.arg(\"update\").arg(\"--check\").arg(\"--json\");\n    if let Some(v) = version {\n        cmd.arg(\"--version\").arg(v);\n    }\n    cmd.stdin(std::process::Stdio::null());\n\n    let output = tokio::time::timeout(CHECK_TIMEOUT, cmd.output())\n        .await\n        .context(\"version check timed out\")?\n        .context(\"failed to spawn `zeroclaw update --check`\")?;\n\n    if !output.status.success() {\n        let stderr = String::from_utf8_lossy(&output.stderr);\n        anyhow::bail!(\"update --check failed: {}\", stderr.trim());\n    }\n\n    let stdout = String::from_utf8_lossy(&output.stdout);\n    serde_json::from_str::<CliCheck>(stdout.trim())\n        .context(\"failed to parse `update --check --json` output\")\n}\n\n/// `GET /api/version/check[?force=true][&version=X]`\n///\n/// Never fails the dashboard: on any error it returns 200 with\n/// `{ is_newer: false, error }` so the version tag degrades gracefully.\npub async fn handle_version_check(\n    State(state): State<AppState>,\n    headers: HeaderMap,\n    Query(q): Query<CheckQuery>,\n) -> impl IntoResponse {\n    if let Err(e) = require_auth(&state, &headers) {\n        return e.into_response();","sourceCodeStart":200,"sourceCodeEnd":236,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-gateway/src/version.rs#L200-L236","documentation":"The gateway version check re-spawns the current executable as `zeroclaw update --check --json` and surfaces the subprocess's trimmed stderr verbatim when it exits non-zero. The real cause is in that stderr text — commonly network failure, an invalid `--version` argument, or an environment where the self-update check cannot run. The HTTP handler degrades gracefully (returns 200 with an `error` field), so this surfaces as a warning, not a failed request.","triggerScenarios":"`GET /api/version/check` with `force=true` or a `version` query param that busts the cache, while `zeroclaw update --check` fails: offline machine, proxy blocking the release host, or a non-semver `version` value the update command cannot parse.","commonSituations":"Air-gapped or proxied environments; passing `?version=latest` instead of a semver string; running a dev build whose self-update metadata is missing.","solutions":["Run `zeroclaw update --check --json` manually and read the stderr reproduced in the message","If a `version` query param is set, pass a valid semver string or omit it entirely","Ensure outbound network/proxy access for the update check; the dashboard degrades gracefully, so this is non-urgent"],"exampleFix":"# before\nGET /api/version/check?version=latest\n# after\nGET /api/version/check\nGET /api/version/check?version=0.7.2","handlingStrategy":"fallback","validationCode":"// Validate a caller-supplied version before it reaches the check:\nfn is_semver_like(v: &str) -> bool {\n    !v.is_empty() && v.chars().next().is_some_and(|c| c.is_ascii_digit())\n      && v.split('.').count() >= 2\n}","typeGuard":null,"tryCatchPattern":"let info = match run_cli_check(version).await {\n    Ok(c) => c,\n    Err(e) => {\n        // Dashboard contract: never fail the request; degrade to a warning payload.\n        return VersionCheckInfo { is_newer: false, error: Some(e.to_string()), ..Default::default() };\n    }\n};","preventionTips":["Cache version-check results and avoid force=true on every dashboard load","Validate any ?version= parameter as semver before passing it through","Treat update-check failures as informational — never block gateway startup or UI on them"],"tags":["version-check","subprocess","self-update","gateway"],"backgroundTag":"subprocess-exit-nonzero","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}