pulumi/pulumi · error

marshalling checkpoint: %w

Error message

marshalling checkpoint: %w

What it means

marshalVersionedCheckpoint fails when diyJSONMarshaler cannot JSON-marshal the checkpoint object being saved as a VersionedCheckpoint. This is a serialization failure before any file is written, so the wrapped JSON marshal error indicates what part of the checkpoint could not be encoded.

Source

Thrown at pkg/backend/diy/state.go:246

	enc.SetEscapeHTML(false)
	if err := enc.Encode(v); err != nil {
		return nil, err
	}
	return bytes.TrimSpace(buf.Bytes()), nil
}

func (compactJSONMarshaler) Unmarshal(data []byte, v any) error {
	return json.Unmarshal(data, v)
}

func marshalVersionedCheckpoint(
	version int,
	features []string,
	checkpoint any,
) (*apitype.VersionedCheckpoint, error) {
	bytes, err := diyJSONMarshaler.Marshal(checkpoint)
	if err != nil {
		return nil, fmt.Errorf("marshalling checkpoint: %w", err)
	}

	return &apitype.VersionedCheckpoint{
		Version:    version,
		Features:   features,
		Checkpoint: json.RawMessage(bytes),
	}, nil
}

func (b *diyBackend) saveCheckpoint(
	ctx context.Context,
	ref *diyBackendReference,
	checkpoint *apitype.VersionedCheckpoint,
) (backupFile string, file string, _ error) {
	// Make a serializable stack and then use the encoder to encode it.
	// stackPath does a bucket listing to find which compression variant exists on disk.
	existingPath := b.stackPath(ctx, ref)
	existingCompression := encoding.CompressionNone

View on GitHub (pinned to 793f7b2e16)

Solutions

  1. Inspect the wrapped error to identify the offending field or marshaler failure.
  2. If it involves secrets, verify your secrets provider is reachable and configured correctly (PULUMI_CONFIG_PASSPHRASE or cloud KMS credentials).
  3. Retry the operation; if it persists, report it as a bug with the wrapped error, since checkpoints should always be marshable.
  4. Fall back to `pulumi stack export` to confirm the existing state is readable, and avoid modifying the stack file manually while debugging.
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure secrets provider config is present before state-mutating ops
if (needsPassphraseProvider && !process.env.PULUMI_CONFIG_PASSPHRASE) {
  throw new Error('PULUMI_CONFIG_PASSPHRASE must be set for this stack');
}

Try / catch

try {
  await pulumi.stack.renameStack(oldName, newName);
} catch (err) {
  if (/marshalling checkpoint/.test(err.message)) {
    // inspect wrapped cause; check secrets provider, retry or report bug
  } else throw err;
}

Prevention

When it happens

Trigger: renameStack (or tests) calling saveStack->marshalVersionedCheckpoint with a checkpoint value containing data that cannot be JSON-marshaled, or an internal marshaler failure (e.g. unsupported types, custom marshaler errors).

Common situations: Rare in normal use since checkpoints are plain JSON-serializable structures; mostly seen with internal bugs, unexpected types in state, or failures from the secrets marshaler when encrypting/decrypting secrets during re-serialization in renameStack.

Related errors


AI-assisted analysis of pulumi/pulumi@793f7b2e16 (2026-08-31). Data as JSON: /api/errors/be4688a00546ddd6. Report an issue: GitHub.