juicedata/juicefs · error

failed to put checkpoint: %w

Error message

failed to put checkpoint: %w

What it means

Save() writes the marshalled checkpoint bytes to the destination storage under m.checkpointKey via dst.Put. This error wraps a Put failure, meaning the checkpoint could not be stored (network error, permission denied, bucket issues, storage backend 5xx). The checkpoint remains unsaved for this round and progress resumption may fall back to the last successful save.

Source

Thrown at pkg/sync/checkpoint.go:307

	dstDelayDelMu.Lock()
	ckpt.DstDelayDel = append([]string(nil), dstDelayDel...)
	dstDelayDelMu.Unlock()
	data, err := json.Marshal(ckpt)
	m.multipartUploadStore.RUnlock()
	for _, state := range ckpt.PrefixState {
		state.RUnlock()
	}
	ckpt.Unlock()

	if err != nil {
		return fmt.Errorf("failed to marshal checkpoint: %w", err)
	}

	logger.Debugf("Saving checkpoint with %d prefixes, copied: %d, failed: %d",
		prefixCount, ckpt.Stats.Copied, ckpt.Stats.Failed)
	reader := bytes.NewReader(data)
	if err := m.dst.Put(ctx, m.checkpointKey, reader); err != nil {
		return fmt.Errorf("failed to put checkpoint: %w", err)
	}

	return nil
}

// ValidateConfig checks if checkpoint config matches current config
func (m *CheckpointManager) ValidateConfig(current *Config) bool {
	old := m.checkpoint.Config

	// Must match fields
	if old.Start != current.Start || old.End != current.End {
		logger.Warnf("Checkpoint config mismatch: start/end, old: %q/%q, current: %q/%q", old.Start, old.End, current.Start, current.End)
		return false
	}

	if !slices.Equal(old.Include, current.Include) || !slices.Equal(old.Exclude, current.Exclude) {
		logger.Warnf("Checkpoint config mismatch: include/exclude, old: %v/%v, current: %v/%v", old.Include, old.Exclude, current.Include, current.Exclude)
		return false

View on GitHub (pinned to c9a67b23e8)

Solutions

  1. Retry the sync/save; Put failures are often transient — reduce checkpoint frequency if throttled
  2. Verify write credentials/permissions on the destination for the checkpoint key path
  3. Check destination storage availability and error details in the wrapped cause (%w)
  4. Use --dry-run or a smaller checkpoint interval to isolate whether the checkpoint key path itself is the problem
Defensive patterns

Strategy: retry

Validate before calling

// Pre-check write access to the destination
if _, err := m.dst.Head(ctx, m.checkpointKey); err != nil && !isNotFound(err) {
	// destination may be misconfigured/unwritable; fix credentials before starting sync
}

Try / catch

if err := mgr.Save(ctx); err != nil {
	if strings.Contains(err.Error(), "failed to put checkpoint") {
		time.Sleep(backoff)
		_ = mgr.Save(ctx) // retry transient Put failures
	}
}

Prevention

When it happens

Trigger: Periodic Save during a running Sync (or tests calling Save directly) where the destination object store rejects the Put: transient network failure, expired/insufficient credentials, bucket not writable, rate limiting, or the destination is offline.

Common situations: Long-running sync across unstable network to S3/OSS; IAM policy lacking PutObject on the checkpoint prefix; disk full when dst is a local path; object-store throttling on frequent checkpoint saves.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06). Data as JSON: /api/errors/1a20f3448c8f9412. Report an issue: GitHub.