abhigyanpatwari/GitNexus · error · ValueError

task {task['id']} did not resolve to an immutable commit

Error message

task {task['id']} did not resolve to an immutable commit

What it means

Raised by resolve_task_bindings when resolved_sha does not match `[0-9a-fA-F]{40,64}` (runner_tasks.py:137-138). This covers both the freshly-resolved ref path and the supplied-pin path: the value must be a raw git object id (40-char SHA-1 or 64-char SHA-256), not a ref name, abbreviated id, or empty string.

Source

Thrown at eval/workflow_bench/runner_tasks.py:138

        repo_identity = Path(repo_output).resolve()
        if expected is None:
            resolved_sha = run_checked(
                [
                    "git",
                    "-C",
                    str(repo_identity),
                    "rev-parse",
                    f"{task.get('ref', 'HEAD')}^{{commit}}",
                ],
                timeout=60,
            ).stdout_tail.strip()
        else:
            supplied = expected[index]
            if not isinstance(supplied, dict):
                raise ValueError(f"task binding {index} must be an object")
            resolved_sha = str(supplied.get("resolved_sha", ""))
        if not re.fullmatch(r"[0-9a-fA-F]{40,64}", resolved_sha):
            raise ValueError(f"task {task['id']} did not resolve to an immutable commit")
        exists = run_managed(
            ["git", "-C", str(repo_identity), "cat-file", "-e", f"{resolved_sha}^{{commit}}"],
            timeout=60,
        )
        if not exists.ok:
            raise ValueError(f"pinned task commit is unavailable for {task['id']}: {resolved_sha}")
        if task_asset_cache is None:
            dependency_binding = capture_task_dependency_binding(
                task,
                repo=repo_identity,
                resolved_sha=resolved_sha.lower(),
            )
        else:
            dependency_binding = task_asset_cache.prepare(
                task,
                repo=repo_identity,
                resolved_sha=resolved_sha.lower(),
            ).dependency_binding

View on GitHub (pinned to d540b00184)

Solutions

  1. Confirm the repo/ref resolves to a real commit: `git -C <repo> rev-parse <ref>^{commit}`.
  2. If using a pin, ensure resolved_sha is the full 40-char (or 64-char) object id.
  3. For an unborn/empty repo, point ref at an existing commit first.

Example fix

// before pin: {"resolved_sha": "abc1234"}
// after pin:  {"resolved_sha": "abc1234567890abcdef0123456789abcdef0123456"}
Defensive patterns

Strategy: validation

Validate before calling

import subprocess, re
sha = subprocess.check_output(
    ["git", "-C", repo, "rev-parse", f"{ref}^{{commit}}"], text=True
).strip()
if not re.fullmatch(r"[0-9a-fA-F]{40,64}", sha):
    raise SystemExit(f"ref did not resolve to a commit object: {sha!r}")

Type guard

import re
def is_full_object_id(sha: str) -> bool:
    return bool(re.fullmatch(r"[0-9a-fA-F]{40,64}", sha))

Try / catch

try:
    bindings = resolve_task_bindings(tasks, expected)
except ValueError as exc:
    if "did not resolve to an immutable commit" in str(exc):
        # regenerate pin from a resolvable ref
        expected = None
        bindings = resolve_task_bindings(tasks, expected)
    else:
        raise

Prevention

When it happens

Trigger: `git rev-parse <ref>^{commit}` returned empty or a symbolic ref (e.g. because the ref is ambiguous/unborn); a supplied pin's resolved_sha is an abbreviated id, a branch name, or missing; the pin JSON has a typo.

Common situations: Pointing ref at an empty repo; using a 7-char short SHA in the pin; the rev-parse failed silently and left resolved_sha blank.

Related errors


AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12). Data as JSON: /api/errors/76f72db6ab446e42. Report an issue: GitHub.