{"record":{"id":"733013e756a09ffd","repo":"NousResearch/hermes-agent","slug":"install-script-pin-commit-other-is-not-a-valid","errorCode":null,"errorMessage":"install script pin commit `{other}` is not a valid git SHA","messagePattern":"install script pin commit `(.+?)` is not a valid git SHA","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"apps/bootstrap-installer/src-tauri/src/install_script.rs","lineNumber":134,"sourceCode":"                source: ScriptSource::DevCheckout,\n                commit: pin.commit.clone(),\n                branch: pin.branch.clone(),\n            });\n        }\n    }\n\n    // 2. (Not implemented) bundled fallback.\n\n    // 3. Network. Pin must be a real commit or a branch ref.\n    //\n    // Commit SHAs are immutable — permanent cache reuse is safe.\n    // Branch/tag pins are moving refs: always try to refresh so \"Retry install\"\n    // cannot keep reusing a poisoned install-main.ps1 forever (#67193).\n    let (commit_or_ref, immutable) = match (&pin.commit, &pin.branch) {\n        (Some(c), _) if is_valid_commit(c) => (c.clone(), true),\n        (_, Some(b)) if !b.trim().is_empty() => (b.clone(), false),\n        (Some(other), _) => {\n            return Err(anyhow!(\n                \"install script pin commit `{other}` is not a valid git SHA\"\n            ));\n        }\n        _ => {\n            return Err(anyhow!(\n                \"no install-script pin supplied — installer cannot resolve a script source\"\n            ));\n        }\n    };\n\n    let cached = cached_path(kind, &commit_or_ref);\n    match cache_plan(immutable, cached.exists()) {\n        CachePlan::Reuse => {\n            emit_log(&format!(\n                \"[bootstrap] using cached {} for {}\",\n                kind.filename(),\n                truncate_ref(&commit_or_ref)\n            ));","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/NousResearch/hermes-agent/blob/c896c09c42910c584c4c7d2325b58c14713ea42c/apps/bootstrap-installer/src-tauri/src/install_script.rs#L116-L152","documentation":"Raised while resolving the install-script source: pin.commit was Some but did not pass is_valid_commit (not a plausible 40/7-hex git SHA). Because commit SHAs are the only immutable, permanently-cacheable pins, an invalid SHA cannot be trusted for cache reuse and resolution aborts rather than falling back to garbage.","triggerScenarios":"Embedding BUILD_PIN_COMMIT with a branch name, short typo'd hash, tag, or truncated/garbage value (e.g. 'main', 'HEAD', 'abczz'); a CI variable that interpolated empty-then-whitespace; a SHA containing uppercase 'G' style placeholders from an unset env var at build time.","commonSituations":"Building the installer locally with BUILD_PIN_COMMIT set from a git describe/branch instead of rev-parse HEAD; CI passing a merge-ref placeholder (GITHUB_PULL_REQUEST refs) that is not a commit SHA; copy-pasting a 7-char hash that picked up a stray character.","solutions":["Set the pin to a full commit SHA: `git rev-parse HEAD` and rebuild the installer with that as BUILD_PIN_COMMIT.","If you meant a moving ref, pass it as the branch pin instead (BUILD_PIN_BRANCH) — branch pins are accepted and simply never cache-reused.","Validate the pin before building: it must be hex (typically 40 chars)."],"exampleFix":"// before (build env)\nBUILD_PIN_COMMIT=main\n\n// after\nBUILD_PIN_COMMIT=$(git rev-parse HEAD)","handlingStrategy":"validation","validationCode":"fn is_valid_commit(s: &str) -> bool {\n    let s = s.trim();\n    (7..=40).contains(&s.len()) && s.chars().all(|c| c.is_ascii_hexdigit())\n}\n\n// At build time, fail fast on a bad pin:\nfn main() {\n    if let Some(c) = option_env!(\"BUILD_PIN_COMMIT\") {\n        assert!(is_valid_commit(c), \"BUILD_PIN_COMMIT `{c}` is not a git SHA; use `git rev-parse HEAD`\");\n    }\n}","typeGuard":"enum ScriptPin {\n    Commit(String),   // immutable, cacheable\n    Branch(String),   // moving ref, always refreshed\n    None,\n}\n\nfn classify_pin(commit: Option<&str>, branch: Option<&str>) -> ScriptPin {\n    match (commit, branch) {\n        (Some(c), _) if is_valid_commit(c) => ScriptPin::Commit(c.to_string()),\n        (_, Some(b)) if !b.trim().is_empty() => ScriptPin::Branch(b.to_string()),\n        _ => ScriptPin::None,\n    }\n}","tryCatchPattern":null,"preventionTips":["Always produce pins with `git rev-parse HEAD`, never from branch names or describe output.","Assert pin validity in build.rs so bad pins fail the build, not the user's install.","Treat branch pins explicitly in tooling so a 'main' value in the commit field is caught early."],"tags":["git","pinning","bootstrap-installer","build-config"],"backgroundTag":null,"analyzedSha":"c896c09c42910c584c4c7d2325b58c14713ea42c","analyzedAt":"2026-08-14T17:18:01.089Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}