dagger/dagger · error

decode persisted container payload: %w

Error message

decode persisted container payload: %w

What it means

Decoding a persisted container failed at the first step: the stored JSON payload could not be unmarshaled into persistedContainerPayload. The cached container entry is corrupt or was written with a different schema than this version expects. The underlying unmarshal error is wrapped for diagnosis.

Source

Thrown at core/container.go:1643

			Owner:          socket.Owner,
		})
	}

	enc, err := json.Marshal(payload)
	if err != nil {
		return dagql.PersistedObjectEncoding{}, fmt.Errorf("marshal persisted container payload: %w", err)
	}
	return dagql.PersistedObjectEncoding{
		JSON:          enc,
		SnapshotLinks: snapshotLinks,
	}, nil
}

//nolint:gocyclo // flat persisted-container dispatch over mount, secret, and socket kinds.
func (*Container) DecodePersistedObject(ctx context.Context, dag *dagql.Server, resultID uint64, call *dagql.ResultCall, payload json.RawMessage) (dagql.Typed, error) {
	var persisted persistedContainerPayload
	if err := json.Unmarshal(payload, &persisted); err != nil {
		return nil, fmt.Errorf("decode persisted container payload: %w", err)
	}
	if persisted.Form == "" {
		persisted.Form = persistedContainerFormReady
	}

	fs := new(LazyAccessor[*Directory, *Container])
	var decodedRootFS decodedContainerDirectoryValue
	if len(persisted.FS) > 0 {
		rootfs, err := decodePersistedContainerDirectoryValue(ctx, dag, resultID, "fs", persisted.FS)
		if err != nil {
			return nil, err
		}
		decodedRootFS = rootfs
		if rootfs.Dir != nil {
			fs.setValue(rootfs.Dir)
		}
	}

View on GitHub (pinned to 82ba2681db)

Solutions

  1. Prune the Dagger engine cache and re-run the pipeline
  2. Align the engine version with the one that wrote the cache entries
  3. Inspect the wrapped error for the specific JSON field mismatch
  4. Re-encode the container result instead of reusing the cached entry

Example fix

// before: reusing stale persisted entry
ctr, err := container.DecodePersistedObject(ctx, dag, resultID, call, payload)
// after: on decode failure, recompute the container
ctr, err := container.DecodePersistedObject(ctx, dag, resultID, call, payload)
if err != nil {
	return recomputeContainer(ctx, dag)
}
Defensive patterns

Strategy: try-catch

Validate before calling

var probe persistedContainerProbe
if err := json.Unmarshal(payload, &probe); err != nil || probe.Form == "" && len(payload) == 0 {
	// treat cache entry as corrupt; skip or prune
}

Try / catch

typed, err := container.DecodePersistedObject(ctx, dag, resultID, call, payload)
if err != nil {
	// corrupt/incompatible entry: recompute the container instead of failing
	return recomputeContainer(ctx, dag)
}

Prevention

When it happens

Trigger: DecodePersistedObject receives a payload whose JSON structure doesn't match persistedContainerPayload — wrong field types, truncated JSON, or entries written by an incompatible Dagger version.

Common situations: Engine upgrade/downgrade across persisted-object schema changes; shared cache backends with mixed engine versions; corrupted cache storage.

Related errors


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