dagger/dagger · error
encode persisted search submatch: nil search submatch
Error message
encode persisted search submatch: nil search submatch
What it means
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.
Source
Thrown at core/search.go:121
var _ dagql.PersistedObject = (*SearchSubmatch)(nil)
var _ dagql.PersistedObjectDecoder = (*SearchSubmatch)(nil)
func (*SearchSubmatch) Type() *ast.Type {
return &ast.Type{
NamedType: "SearchSubmatch",
NonNull: true,
}
}
type persistedSearchSubmatch struct {
Text string `json:"text"`
Start int `json:"start"`
End int `json:"end"`
}
func (m *SearchSubmatch) EncodePersistedObject(context.Context, dagql.PersistedObjectCache) (dagql.PersistedObjectEncoding, error) {
if m == nil {
return dagql.PersistedObjectEncoding{}, fmt.Errorf("encode persisted search submatch: nil search submatch")
}
return encodePersistedObjectPayload(persistedSearchSubmatch{
Text: m.Text,
Start: m.Start,
End: m.End,
})
}
func (*SearchSubmatch) DecodePersistedObject(_ context.Context, _ *dagql.Server, _ uint64, _ *dagql.ResultCall, payload json.RawMessage) (dagql.Typed, error) {
var persisted persistedSearchSubmatch
if err := json.Unmarshal(payload, &persisted); err != nil {
return nil, fmt.Errorf("decode persisted search submatch payload: %w", err)
}
return &SearchSubmatch{
Text: persisted.Text,
Start: persisted.Start,
End: persisted.End,
}, nilView on GitHub (pinned to 82ba2681db)
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
Example fix
// before
subs := r.Submatches
// after
subs := make([]*SearchSubmatch, 0, len(r.Submatches))
for _, m := range r.Submatches {
if m != nil {
subs = append(subs, m)
}
} Defensive patterns
Strategy: validation
Validate before calling
// drop nil submatches before persisting
subs := make([]*SearchSubmatch, 0, len(r.Submatches))
for _, m := range r.Submatches {
if m != nil { subs = append(subs, m) }
} Type guard
func isValidSubmatch(m *SearchSubmatch) bool { return m != nil } Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- encode persisted search result: nil search result
- decode persisted container withEntrypoint lazy payload: %w
- decode persisted container withoutEntrypoint lazy payload: %
- decode persisted container withDefaultArgs lazy payload: %w
- decode persisted container withoutDefaultArgs lazy payload:
AI-assisted analysis of dagger/dagger@82ba2681db (2026-09-05).
Data as JSON: /api/errors/322a782b4fdf38e0.
Report an issue: GitHub.