xai-org/grok-build · error

unsupported checkout target (need a full commit oid or a sim

Error message

unsupported checkout target (need a full commit oid or a simple git ref): {target}

What it means

fetch_checkout_target_if_missing fetches a checkout target from origin only when it can map the target to a safe fetch spec via origin_fetch_spec_for_checkout_target. That mapping accepts full 40/64-hex object ids, simple safe git refs (branch names, refs/heads/…, refs/tags/…), and rewrites local remote-tracking names (origin/foo, refs/remotes/origin/foo) to the remote branch. This error is thrown for anything else: empty strings, targets starting with '-' (option-injection risk), refs containing ':', '*', '?', '[', backslash, whitespace, '..' or '@{', and abbreviated SHAs, which checkout locally but cannot be fetched from origin.

Source

Thrown at crates/codegen/xai-grok-workspace/src/restore_fetch.rs:269

        .current_dir(repo)
        .args(["cat-file", "-t", spec])
        .stdout(Stdio::null())
        .stderr(Stdio::null())
        .output();
    matches!(output, Ok(o) if o.status.success())
}

/// Fetch a checkout target (full oid or simple ref) if it is not already local.
///
/// # Errors
///
/// Unsafe/unsupported spec, spawn failure, timeout, or non-zero git exit.
pub(crate) fn fetch_checkout_target_if_missing(
    repo: &Path,
    target: &str,
) -> Result<FetchCommitOutcome> {
    let Some(spec) = origin_fetch_spec_for_checkout_target(target) else {
        bail!("unsupported checkout target (need a full commit oid or a simple git ref): {target}");
    };
    if is_full_object_id(spec) {
        return fetch_commit_if_missing(repo, spec);
    }
    fetch_refspec_from_origin(repo, spec, RESTORE_FETCH_BUDGET)?;
    Ok(FetchCommitOutcome::Fetched)
}

fn is_shallow_repository(repo: &Path) -> bool {
    let output = git_command()
        .current_dir(repo)
        .args(["rev-parse", "--is-shallow-repository"])
        .stdout(Stdio::piped())
        .stderr(Stdio::null())
        .output();
    matches!(
        output,
        Ok(o) if o.status.success() && String::from_utf8_lossy(&o.stdout).trim() == "true"

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Pass the full 40- or 64-character lowercase hex object id instead of an abbreviated SHA — resolve it with `git rev-parse <sha>` in a repo that has it, or fetch by branch/tag
  2. Use a simple safe ref (branch name, refs/heads/…, refs/tags/…) as the checkout target instead of a range, wildcard, or rev expression
  3. Fix the source of the bad target (snapshot manifest / user config) to store full oids or plain ref names; trim stray whitespace and arrow-style log output
  4. If the commit only exists locally under an abbreviated form, expand it first (`git rev-parse --verify <abbrev>^{commit}`) before requesting a fetch

Example fix

// before: abbreviated SHA cannot be fetched from origin
fetch_checkout_target_if_missing(repo, "a1b2c3d")?;
// after: resolve to the full oid first
let full = git_rev_parse(repo, "a1b2c3d")?; // "a1b2c3d…" (40 hex chars)
fetch_checkout_target_if_missing(repo, &full)?;
Defensive patterns

Strategy: validation

Validate before calling

use crate::restore_fetch::{origin_fetch_spec_for_checkout_target, is_full_object_id};
fn checkout_target_fetchable(target: &str) -> bool {
    origin_fetch_spec_for_checkout_target(target).is_some()
}
// call before the API: assert!(checkout_target_fetchable(target), "use a full oid or simple ref");

Type guard

fn is_fetchable_checkout_target(target: &str) -> bool {
    is_full_object_id(target)
        || (!target.is_empty()
            && !target.starts_with('-')
            && !target.contains([':', '*', '?', '[', '\\', ' ', '\t', '\n', '\r'])
            && !target.contains("..")
            && !target.contains("{"))
}

Try / catch

match fetch_checkout_target_if_missing(repo, target) {
    Ok(outcome) => outcome,
    Err(e) if e.to_string().starts_with("unsupported checkout target") => {
        let full = expand_to_full_oid(repo, target) // git rev-parse --verify <target>^{commit}
            .context("target must be a full commit oid or simple git ref")?;
        fetch_checkout_target_if_missing(repo, &full)?
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling fetch_checkout_target_if_missing with an abbreviated SHA (e.g. 7-char commit prefix); a target with glob/range characters like 'main..other' or 'v1.*'; an empty or dash-prefixed target; a rev expression or log-pasted string (e.g. 'origin/HEAD -> origin/main') that origin_fetch_spec_for_checkout_target maps to None.

Common situations: User config or a snapshot manifest storing an abbreviated commit SHA instead of the full oid; a checkout target recorded as a revision range or wildcard refspec; targets pasted from git logs with arrow-style prefixes; corrupted restore metadata passing empty strings.

Related errors


AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31). Data as JSON: /api/errors/2dacb86090453b90. Report an issue: GitHub.