{"record":{"id":"8fc8d5e6ed041596","repo":"pulumi/pulumi","slug":"getting-head-commit-info-w","errorCode":null,"errorMessage":"getting HEAD commit info: %w","messagePattern":"getting HEAD commit info: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/cmd/pulumi/metadata/metadata.go","lineNumber":467,"sourceCode":"}\n\nfunc addGitCommitMetadata(repo *git.Repository, repoRoot string, m *backend.UpdateMetadata) error {\n\t// When running in a CI/CD environment, the current git repo may be running from a\n\t// detached HEAD and may not have have the latest commit message. We fall back to\n\t// CI-system specific environment variables when possible.\n\tciVars := ciutil.DetectVars()\n\n\t// Commit at HEAD\n\thead, err := repo.Head()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"getting repository HEAD: %w\", err)\n\t}\n\n\thash := head.Hash()\n\tm.Environment[backend.GitHead] = hash.String()\n\tcommit, commitErr := repo.CommitObject(hash)\n\tif commitErr != nil {\n\t\treturn fmt.Errorf(\"getting HEAD commit info: %w\", commitErr)\n\t}\n\n\t// If in detached head, will be \"HEAD\", and fallback to use value from CI/CD system if possible.\n\t// Otherwise, the value will be like \"refs/heads/master\".\n\theadName := head.Name().String()\n\tif headName == \"HEAD\" && ciVars.BranchName != \"\" {\n\t\theadName = ciVars.BranchName\n\t}\n\tif headName != \"HEAD\" {\n\t\tm.Environment[backend.GitHeadName] = headName\n\t}\n\n\t// If there is no message set manually, default to the Git commit's title.\n\tmsg := strings.TrimSpace(commit.Message)\n\tif msg == \"\" && ciVars.CommitMessage != \"\" {\n\t\tmsg = ciVars.CommitMessage\n\t}\n\tif m.Message == \"\" {","sourceCodeStart":449,"sourceCodeEnd":485,"githubUrl":"https://github.com/pulumi/pulumi/blob/793f7b2e160db4321fb7fb6b0607461e01cb251e/pkg/cmd/pulumi/metadata/metadata.go#L449-L485","documentation":"Returned when repo.CommitObject(hash) fails to load the commit object that HEAD points to. The hash was resolved but the underlying commit object is missing or unreadable, so author/committer/message metadata cannot be set.","triggerScenarios":"Shallow clones or CI checkouts where HEAD's commit object was not fetched (grafted/shallow history); corrupted or pruned git object store; HEAD resolving to a tag/annotated object that is not a commit.","commonSituations":"GitHub Actions/GitLab CI with fetch-depth: 1 combined with history rewriting; repos with gc-pruned objects; HEAD pointing at a tag object.","solutions":["Fetch full history: git fetch --unshallow (or increase fetch-depth in CI)","Run git fsck to detect and diagnose corrupt/missing objects","Verify git cat-file -t $(git rev-parse HEAD) returns 'commit'","Re-clone the repository if the object store is damaged"],"exampleFix":"# before: GitHub Actions\n- uses: actions/checkout@v4\n  with:\n    fetch-depth: 1\n# after\n- uses: actions/checkout@v4\n  with:\n    fetch-depth: 0","handlingStrategy":"try-catch","validationCode":"if err := exec.Command(\"git\", \"cat-file\", \"-t\", \"HEAD\").Run(); err != nil {\n    return errors.New(\"HEAD object missing or corrupt; fetch full history\")\n}","typeGuard":null,"tryCatchPattern":"if commitErr != nil {\n    if errors.Is(commitErr, object.ErrObjectNotFound) {\n        return fmt.Errorf(\"HEAD commit object not fetched (shallow clone?): %w\", commitErr)\n    }\n    return fmt.Errorf(\"getting HEAD commit info: %w\", commitErr)\n}","preventionTips":["Avoid fetch-depth: 1 in CI, or run git fetch --unshallow","Run git fsck periodically to catch object corruption","Don't point HEAD at non-commit objects (tags) in automation"],"tags":["git","go-git","corrupt-object"],"backgroundTag":"git-commit-object-missing","analyzedSha":"793f7b2e160db4321fb7fb6b0607461e01cb251e","analyzedAt":"2026-08-31T09:36:43.099Z","schemaVersion":2},"datasetVersion":"2026-09-01T08:17:40.651Z"}