{"record":{"id":"322a782b4fdf38e0","repo":"dagger/dagger","slug":"encode-persisted-search-submatch-nil-search-subma","errorCode":null,"errorMessage":"encode persisted search submatch: nil search submatch","messagePattern":"encode persisted search submatch: nil search submatch","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/search.go","lineNumber":121,"sourceCode":"var _ dagql.PersistedObject = (*SearchSubmatch)(nil)\nvar _ dagql.PersistedObjectDecoder = (*SearchSubmatch)(nil)\n\nfunc (*SearchSubmatch) Type() *ast.Type {\n\treturn &ast.Type{\n\t\tNamedType: \"SearchSubmatch\",\n\t\tNonNull:   true,\n\t}\n}\n\ntype persistedSearchSubmatch struct {\n\tText  string `json:\"text\"`\n\tStart int    `json:\"start\"`\n\tEnd   int    `json:\"end\"`\n}\n\nfunc (m *SearchSubmatch) EncodePersistedObject(context.Context, dagql.PersistedObjectCache) (dagql.PersistedObjectEncoding, error) {\n\tif m == nil {\n\t\treturn dagql.PersistedObjectEncoding{}, fmt.Errorf(\"encode persisted search submatch: nil search submatch\")\n\t}\n\treturn encodePersistedObjectPayload(persistedSearchSubmatch{\n\t\tText:  m.Text,\n\t\tStart: m.Start,\n\t\tEnd:   m.End,\n\t})\n}\n\nfunc (*SearchSubmatch) DecodePersistedObject(_ context.Context, _ *dagql.Server, _ uint64, _ *dagql.ResultCall, payload json.RawMessage) (dagql.Typed, error) {\n\tvar persisted persistedSearchSubmatch\n\tif err := json.Unmarshal(payload, &persisted); err != nil {\n\t\treturn nil, fmt.Errorf(\"decode persisted search submatch payload: %w\", err)\n\t}\n\treturn &SearchSubmatch{\n\t\tText:  persisted.Text,\n\t\tStart: persisted.Start,\n\t\tEnd:   persisted.End,\n\t}, nil","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/dagger/dagger/blob/82ba2681dbe30d3547a1dc50ea495900ab5b6047/core/search.go#L103-L139","documentation":"SearchSubmatch implements the dagql PersistedObject interface. This guard fires when EncodePersistedObject is called on a nil *SearchSubmatch receiver; a nil submatch cannot be serialized, so an explicit error is returned. Note the SearchResult encoder itself skips nil submatches, so this indicates a direct encoding of a nil submatch elsewhere.","triggerScenarios":"An internal cache/encoding path calls EncodePersistedObject directly on a nil *SearchSubmatch, e.g. a submatch slice entry that was nil being persisted individually by the dagql cache.","commonSituations":"Engine-internal bug where a nil submatch reaches the persisted-object cache; typically surfaced as an unexpected failure while caching search results in a saved operation/replay.","solutions":["Filter nil submatches before persisting search results","Upgrade Dagger to a version where this path skips nils","Re-run the query to regenerate the cache entry","File an issue with the query if it reproduces"],"exampleFix":"// before\nsubs := r.Submatches\n// after\nsubs := make([]*SearchSubmatch, 0, len(r.Submatches))\nfor _, m := range r.Submatches {\n  if m != nil {\n    subs = append(subs, m)\n  }\n}","handlingStrategy":"validation","validationCode":"// drop nil submatches before persisting\nsubs := make([]*SearchSubmatch, 0, len(r.Submatches))\nfor _, m := range r.Submatches {\n  if m != nil { subs = append(subs, m) }\n}","typeGuard":"func isValidSubmatch(m *SearchSubmatch) bool { return m != nil }","tryCatchPattern":null,"preventionTips":["Never append nil submatches to SearchResult.Submatches","Skip nils in decode/encode loops as the core code does","Upgrade Dagger to pick up engine-side fixes"],"tags":["dagger","search","cache","serialization","nil-pointer"],"backgroundTag":"nil-persisted-object-encoding","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"}