dagger/dagger · error
load persisted %s snapshot links query: %w
Error message
load persisted %s snapshot links query: %w
What it means
Wraps failures from persistedDecodeQuery, which extracts the *Query from the dagql server's root object. This error means the dagql server passed to DecodePersistedObject is nil, has a nil root, or its root is not a *Query, so persisted snapshot links cannot be loaded.
Source
Thrown at core/persisted_object.go:144
}
links, err := cache.PersistedSnapshotLinksByResultID(ctx, resultID)
if err != nil {
return dagql.PersistedSnapshotRefLink{}, fmt.Errorf("load persisted %s snapshot link: %w", label, err)
}
for _, link := range links {
if link.Role == role {
return link, nil
}
}
return dagql.PersistedSnapshotRefLink{}, fmt.Errorf("missing persisted %s snapshot link role %q for result %d", label, role, resultID)
}
func loadPersistedSnapshotLinksByResultID(ctx context.Context, dag *dagql.Server, resultID uint64, label string) ([]dagql.PersistedSnapshotRefLink, error) {
if resultID == 0 {
return nil, fmt.Errorf("load persisted %s snapshot links: zero result ID", label)
}
if _, err := persistedDecodeQuery(dag); err != nil {
return nil, fmt.Errorf("load persisted %s snapshot links query: %w", label, err)
}
cache, err := dagql.EngineCache(ctx)
if err != nil {
return nil, fmt.Errorf("load persisted %s snapshot links cache: %w", label, err)
}
links, err := cache.PersistedSnapshotLinksByResultID(ctx, resultID)
if err != nil {
return nil, fmt.Errorf("load persisted %s snapshot links: %w", label, err)
}
return links, nil
}
func loadPersistedImmutableSnapshotByResultID(ctx context.Context, dag *dagql.Server, resultID uint64, label, role string) (bkcache.ImmutableRef, error) {
link, err := loadPersistedSnapshotLinkByResultID(ctx, dag, resultID, label, role)
if err != nil {
return nil, err
}
query, err := persistedDecodeQuery(dag)View on GitHub (pinned to 82ba2681db)
Solutions
- Ensure the dagql.Server passed to decode functions was created with the engine's *Query as its root object.
- Check for nil before calling: verify dag and dag.Root() are non-nil.
- If running in a test harness, construct the server the same way the engine does (root *Query) instead of a stub.
Example fix
// before
srv := dagql.NewServer(myCustomRoot{}) // root is not *Query
obj, err := DecodePersistedObject(ctx, srv, payload)
// after
srv := dagql.NewServer(query) // query is *core.Query
obj, err := DecodePersistedObject(ctx, srv, payload) Defensive patterns
Strategy: try-catch
Validate before calling
if dag == nil || dag.Root() == nil {
return fmt.Errorf("dagql server not initialized")
} Type guard
if q, ok := dagql.UnwrapAs[*core.Query](dag.Root()); ok {
// root is a *Query, safe to decode
} Try / catch
obj, err := DecodePersistedObject(ctx, dag, payload)
if err != nil && strings.Contains(err.Error(), "persisted decode query") {
// server root is not *Query; re-init server with Query root
} Prevention
- Construct dagql.Server with the engine's *Query as root.
- Nil-check the server before decode calls.
- Keep test harnesses rooted with *core.Query.
When it happens
Trigger: loadPersistedSnapshotLinksByResultID is called (via DecodePersistedObject) with a dag server whose root object was not constructed as *Query — e.g. a test server rooted at a different object, or a nil server passed in.
Common situations: Tests spinning up a dagql.Server with a custom root type; calling decode helpers before the engine finishes initializing the root query; refactoring that changed the root object type.
Related errors
- encode persisted generated code: nil generated code
- encode persisted generated code: missing code directory
- decode persisted generated code: missing code directory
- decode persisted container withoutAnnotation lazy payload: %
- decode persisted container withSecretVariable lazy payload:
AI-assisted analysis of dagger/dagger@82ba2681db (2026-09-05).
Data as JSON: /api/errors/92d00b3099ca608f.
Report an issue: GitHub.