dagger/dagger · error
missing persisted %s snapshot link role %q for result %d
Error message
missing persisted %s snapshot link role %q for result %d
What it means
The cache returned snapshot links for the result ID, but none matched the requested role string. The persisted record exists but lacks a link for the specific role (e.g. input vs output snapshot) the decoder needs, indicating an incomplete or differently-versioned persisted record.
Source
Thrown at core/persisted_object.go:136
return dagql.PersistedSnapshotRefLink{}, fmt.Errorf("load persisted %s snapshot link: zero result ID", label)
}
if _, err := persistedDecodeQuery(dag); err != nil {
return dagql.PersistedSnapshotRefLink{}, fmt.Errorf("load persisted %s snapshot link query: %w", label, err)
}
cache, err := dagql.EngineCache(ctx)
if err != nil {
return dagql.PersistedSnapshotRefLink{}, fmt.Errorf("load persisted %s snapshot link cache: %w", label, err)
}
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, nilView on GitHub (pinned to 82ba2681db)
Solutions
- Verify the persisted payload was written by a version that records the requested role; re-persist if not.
- Check which roles exist for the result ID and use the correct role string.
- Handle role absence gracefully for legacy payloads (skip snapshot or backfill).
- Confirm the role constant used at persist time matches the one at decode time.
Example fix
// before
link, err := loadPersistedSnapshotLinkByResultID(ctx, dag, id, "container", roleOutputSnapshot)
// after
links, err := loadPersistedSnapshotLinksByResultID(ctx, dag, id, "container")
if len(links) == 0 { /* legacy payload: proceed without snapshot */ } Defensive patterns
Strategy: fallback
Validate before calling
links, err := cache.PersistedSnapshotLinksByResultID(ctx, resultID)
if err == nil && !hasRole(links, role) {
// use legacy path or backfill before decode
} Type guard
func hasRole(links []dagql.PersistedSnapshotRefLink, role string) bool {
for _, l := range links {
if l.Role == role { return true }
}
return false
} Try / catch
err := decodePersistedObject(ctx, dag, id)
if err != nil && strings.Contains(err.Error(), "snapshot link role") {
// decode without snapshot or migrate the payload
} Prevention
- Persist payloads with all roles the decoder expects.
- Keep producer and decoder versions in sync on role names.
- Support legacy payloads missing newer roles.
- Share role constants, not string literals.
When it happens
Trigger: loadPersistedSnapshotLinkByResultID iterating links and finding no link.Role == role when called from DecodePersistedObject or loadPersistedImmutableSnapshotByResultID — e.g. a payload persisted by an older version that didn't record the requested role.
Common situations: Version drift between the code that persisted the payload and the code decoding it (role names or roles recorded changed); manual payload construction omitting a role; role string typo in custom tooling.
Related errors
- load persisted %s snapshot link cache: %w
- load persisted %s snapshot link: %w
- failed to get ref for source directory: %w
- unknown type %q
- enum types must be named
AI-assisted analysis of dagger/dagger@82ba2681db (2026-09-05).
Data as JSON: /api/errors/95ed4f491079e832.
Report an issue: GitHub.