GoogleContainerTools/skaffold · error
failed to checkout commit: %w
Error message
failed to checkout commit: %w
What it means
Thrown by syncRepo when the fallback clone succeeded but `git checkout <ref>` fails inside the fresh cache clone. This happens when the requested ref is not present in the default-branch-only shallow clone (depth 1). If the partial cache dir could not be removed, its removal error is additionally wrapped into this error.
Source
Thrown at pkg/skaffold/git/gitutil.go:139
}
repoCacheDir := filepath.Join(skaffoldCacheDir, hash)
if _, err := os.Stat(repoCacheDir); os.IsNotExist(err) {
if opts.SyncRemoteCache.CloneDisabled() {
return "", SyncDisabledErr(g, repoCacheDir)
}
if _, err := r.Run(ctx, "clone", g.RepoCloneURI, fmt.Sprintf("./%s", hash), "--branch", ref, "--depth", "1"); err != nil {
if strings.Contains(err.Error(), "Could not find remote branch") {
if _, err := r.Run(ctx, "clone", g.RepoCloneURI, fmt.Sprintf("./%s", hash), "--depth", "1"); err != nil {
return "", fmt.Errorf("failed to clone repo: %w", err)
}
r.Dir = repoCacheDir
if _, err := r.Run(ctx, "checkout", ref); err != nil {
if rmErr := os.RemoveAll(repoCacheDir); rmErr != nil {
err = fmt.Errorf("failed to remove repo cache dir: %w", rmErr)
}
return "", fmt.Errorf("failed to checkout commit: %w", err)
}
} else {
return "", fmt.Errorf("failed to clone repo: %w", err)
}
}
} else {
r.Dir = repoCacheDir
// check remote is defined
if remotes, err := r.Run(ctx, "remote", "-v"); err != nil {
return "", fmt.Errorf("failed to clone repo %s: trouble checking repository remote; run 'git clone <REPO>; stat <DIR/SUBDIR>' to verify credentials: %w", g.Repo, err)
} else if len(remotes) == 0 {
return "", fmt.Errorf("failed to clone repo %s: remote not set for existing clone", g.Repo)
}
// if sync property is false, then skip fetching latest from remote and resetting the branch.
if g.Sync != nil && !*g.Sync {
return repoCacheDir, nil
}View on GitHub (pinned to a1189de023)
Solutions
- Verify the ref exists on the remote: git ls-remote <URI> <ref>, and correct the ref in config.
- Use a branch or tag name instead of a raw commit SHA — shallow clones only fetch the branch tip.
- Manually remove the partial cache directory (<remote-cache-dir>/<hash>) so the next run re-clones cleanly.
- Upgrade skaffold; newer versions handle shallow-clone checkout of arbitrary SHAs better.
Example fix
// before repo: https://github.com/org/repo#a1b2c3d # SHA not in shallow depth-1 clone // after repo: https://github.com/org/repo#main
Defensive patterns
Strategy: validation
Validate before calling
const { execSync } = require('child_process');
function refIsBranchOrTag(uri, ref) {
const out = execSync(`git ls-remote ${uri} refs/heads/${ref} refs/tags/${ref}`, { encoding: 'utf8' });
return out.trim().length > 0;
} Type guard
function isResolvableRef(ref) {
// branch/tag names are shallow-clone safe; raw SHAs are not
return /^[A-Za-z0-9._/-]+$/.test(ref) && !/^[0-9a-f]{40}$/i.test(ref);
} Try / catch
try {
await syncRepo(g, ctx, opts);
} catch (err) {
if (/failed to checkout commit/.test(err.message)) {
fs.rmSync(path.join(cacheDir, hashFor(g)), { recursive: true, force: true });
throw new Error(`Ref ${g.ref} not available in shallow clone; use a branch/tag or full clone.`);
}
throw err;
} Prevention
- Configure branch/tag refs, not commit SHAs, when relying on skaffold's depth-1 clones.
- Confirm refs with git ls-remote before adding them to config.
- After any failure, rm -rf the per-repo cache dir so the next attempt is clean.
- If SHAs are required, pre-clone the repo yourself with a full fetch.
When it happens
Trigger: git clone succeeded without --branch (because --branch <ref> said the ref was missing), then git checkout <ref> also fails: ref genuinely doesn't exist, or exists only in history beyond the depth-1 shallow clone / on other branches.
Common situations: Requesting an old commit SHA with a shallow clone; ref exists on a non-default branch not fetched by depth-1 clone; ref name typo (case-sensitive); the remote branch was force-pushed/renamed between attempts.
Related errors
- CONFIG_REMOTE_REPO_CACHE_NOT_FOUND_ERR
- getting tags: %w
- failed to clone repo %s: trouble building repo URI with toke
- failed to get default branch for repo %s
- failed to lookup %s branch for repo %s: %w
AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05).
Data as JSON: /api/errors/e2fc5032c51f7167.
Report an issue: GitHub.