{"record":{"id":"8fe3f52b1fa2a88e","repo":"dagger/dagger","slug":"encode-persisted-git-commit-missing-ref","errorCode":null,"errorMessage":"encode persisted git commit: missing ref","messagePattern":"encode persisted git commit: missing ref","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/git.go","lineNumber":643,"sourceCode":"\t\tRepo:    repo,\n\t\tBackend: backend,\n\t\tRef:     ref,\n\t}, nil\n}\n\ntype persistedGitCommitPayload struct {\n\tRepoResultID uint64 `json:\"repoResultID\"`\n\tSHA          string `json:\"sha\"`\n\tFetchName    string `json:\"fetchName,omitempty\"`\n}\n\nfunc (commit *GitCommit) EncodePersistedObject(ctx context.Context, cache dagql.PersistedObjectCache) (dagql.PersistedObjectEncoding, error) {\n\t_ = ctx\n\tif commit == nil {\n\t\treturn dagql.PersistedObjectEncoding{}, fmt.Errorf(\"encode persisted git commit: nil commit\")\n\t}\n\tif commit.Ref == nil {\n\t\treturn dagql.PersistedObjectEncoding{}, fmt.Errorf(\"encode persisted git commit: missing ref\")\n\t}\n\tif commit.Ref.SHA == \"\" {\n\t\treturn dagql.PersistedObjectEncoding{}, fmt.Errorf(\"encode persisted git commit: missing commit SHA\")\n\t}\n\trepoID, err := encodePersistedObjectRef(cache, commit.Repo, \"git commit repo\")\n\tif err != nil {\n\t\treturn dagql.PersistedObjectEncoding{}, err\n\t}\n\tfetchName := \"\"\n\tif commit.FetchRef != nil {\n\t\tfetchName = commit.FetchRef.Name\n\t}\n\tpayloadJSON, err := json.Marshal(persistedGitCommitPayload{\n\t\tRepoResultID: repoID,\n\t\tSHA:          commit.Ref.SHA,\n\t\tFetchName:    fetchName,\n\t})\n\tif err != nil {","sourceCodeStart":625,"sourceCodeEnd":661,"githubUrl":"https://github.com/dagger/dagger/blob/82ba2681dbe30d3547a1dc50ea495900ab5b6047/core/git.go#L625-L661","documentation":"Thrown by GitCommit.EncodePersistedObject when the commit's embedded Ref pointer is nil. A GitCommit derives its SHA and identity from its gitutil.Ref, so without a Ref the commit cannot be serialized into the persisted-object payload.","triggerScenarios":"Encoding a *GitCommit that has Repo set but Ref left nil — e.g. manual construction, or a decode path that built a commit without attaching its Ref.","commonSituations":"Hand-assembled GitCommit structs in custom tooling; refactors that changed how Ref is attached; partial initialization after DecodePersistedObject changes.","solutions":["Set commit.Ref = &gitutil.Ref{SHA: <sha>} (and Name for refs) before encoding","Construct commits via the dagql GitRepository APIs so Ref is populated automatically","Add a pre-encode validation: if commit.Ref == nil { return descriptive error }","Trace where the commit was created and ensure the branch/tag/commit resolution assigns Ref"],"exampleFix":"// before\ncommit := &GitCommit{Repo: repo}\nenc, err := commit.EncodePersistedObject(ctx, cache) // missing ref\n// after\ncommit := &GitCommit{Repo: repo, Ref: &gitutil.Ref{SHA: sha}}\nenc, err := commit.EncodePersistedObject(ctx, cache)","handlingStrategy":"validation","validationCode":"if commit == nil || commit.Ref == nil {\n\treturn fmt.Errorf(\"GitCommit requires a populated Ref before encoding\")\n}","typeGuard":"func commitHasRef(c *GitCommit) bool { return c != nil && c.Ref != nil }","tryCatchPattern":"enc, err := commit.EncodePersistedObject(ctx, cache)\nif err != nil {\n\treturn fmt.Errorf(\"persist git commit: %w\", err)\n}","preventionTips":["Set Ref (and SHA) immediately when constructing a GitCommit","Prefer API-provided commits over manual assembly","Lint for GitCommit literals missing Ref"],"tags":["git","serialization","persisted-object","nil-pointer"],"backgroundTag":"nil-struct-field-before-serialize","analyzedSha":"82ba2681dbe30d3547a1dc50ea495900ab5b6047","analyzedAt":"2026-09-05T07:21:37.930Z","contentChangedAt":"2026-09-05T07:21:37.930Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}