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

  1. Use the context handed to the engine operation (e.g. the resolver ctx) rather than a fresh context.Background().
  2. Ensure the engine session is still alive when decoding persisted objects.
  3. 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

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


AI-assisted analysis of dagger/dagger@82ba2681db (2026-09-05). Data as JSON: /api/errors/5876361da77db5b8. Report an issue: GitHub.