dagger/dagger · error
load persisted %s snapshot links cache: %w
Error message
load persisted %s snapshot links cache: %w
What it means
Wraps a failure from dagql.EngineCache(ctx), which retrieves the engine cache from the context. Without the engine cache the persisted snapshot-link table cannot be consulted during persisted-object decoding.
Source
Thrown at core/persisted_object.go:148
}
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)
if err != nil {
return nil, err
}
ref, err := query.SnapshotManager().GetBySnapshotID(ctx, link.RefKey, bkcache.NoUpdateLastUsed)View on GitHub (pinned to 82ba2681db)
Solutions
- Use the context handed to the engine operation (e.g. the resolver ctx) rather than a fresh context.Background().
- Ensure the engine session is still alive when decoding persisted objects.
- If running tests, bootstrap the context with the same engine cache installation the engine performs.
Example fix
// before decoded, _ := DecodePersistedObject(context.Background(), dag, payload) // after decoded, err := DecodePersistedObject(ctx, dag, payload) // ctx from the engine resolver/session
Defensive patterns
Strategy: try-catch
Try / catch
links, err := loadPersistedSnapshotLinksByResultID(ctx, dag, id, label)
if err != nil && strings.Contains(err.Error(), "snapshot links cache") {
// engine cache missing from ctx: use engine-provided ctx
} Prevention
- Never strip values with context.Background() in the middle of engine work.
- Ensure the engine session is alive during persisted-object decoding.
- Pass resolver contexts through to helper goroutines.
When it happens
Trigger: DecodePersistedObject runs loadPersistedSnapshotLinksByResultID in a context that lacks the engine cache value — e.g. a context created outside the engine session or after session teardown.
Common situations: Calling decode helpers from tests with a bare context.Background(); executing persisted-object decoding after the Dagger session/engine has been shut down; spawning a goroutine with a stripped context.
Related errors
- get current query for cache locks: %w
- directory no-op equivalence client metadata: %w
- engine cache: %w
- current call is nil
- resolve volatile variable %q: current dagql cache: %w
AI-assisted analysis of dagger/dagger@82ba2681db (2026-09-05).
Data as JSON: /api/errors/5876361da77db5b8.
Report an issue: GitHub.