benbjohnson/litestream · error

replica client does not support v0.3.x restore

Error message

replica client does not support v0.3.x restore

What it means

RestoreV3 restores from the legacy v0.3.x backup format, which requires the configured replica client to also implement the ReplicaClientV3 interface. This error means the active client (a modern v0.5+ backend) does not implement that interface, so a v0.3.x-format restore cannot be performed against it.

Source

Thrown at replica.go:1070

		}
		if _, err := closeLevel(nil); err != nil {
			return currentTXID, err
		}

		// If we made progress at this level, restart from level 1.
		if currentTXID > afterTXID {
			return currentTXID, nil
		}
	}

	return currentTXID, nil
}

// RestoreV3 restores from a v0.3.x format backup.
func (r *Replica) RestoreV3(ctx context.Context, opt RestoreOptions) error {
	client, ok := r.Client.(ReplicaClientV3)
	if !ok {
		return fmt.Errorf("replica client does not support v0.3.x restore")
	}

	// Validate options.
	if opt.OutputPath == "" {
		return fmt.Errorf("output path required")
	} else if opt.IntegrityCheck != IntegrityCheckNone && opt.IntegrityCheck != IntegrityCheckQuick && opt.IntegrityCheck != IntegrityCheckFull {
		return fmt.Errorf("unsupported integrity check mode: %d", opt.IntegrityCheck)
	}

	// Ensure output path does not already exist.
	if _, err := os.Stat(opt.OutputPath); err == nil {
		return fmt.Errorf("cannot restore, output path already exists: %s", opt.OutputPath)
	} else if !os.IsNotExist(err) {
		return err
	}

	// Find all generations.
	generations, err := client.GenerationsV3(ctx)

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Restore v0.3.x backups using litestream v0.3.x binary instead
  2. Use a client implementation that implements ReplicaClientV3 for the legacy restore path
  3. Migrate the old backup: restore with v0.3.x, then re-replicate with the current litestream version
  4. If you intend a normal restore, call Restore (not RestoreV3) against the modern client

Example fix

// before
if err := r.RestoreV3(ctx, opt); err != nil { ... } // client lacks ReplicaClientV3
// after: normal restore on the modern client
if err := r.Restore(ctx, opt); err != nil { ... }
Defensive patterns

Strategy: type-guard

Validate before calling

func supportsV3Restore(r *litestream.Replica) bool {
    _, ok := r.Client.(litestream.ReplicaClientV3)
    return ok
}

// before restoring:
if !supportsV3Restore(replica) {
    return errors.New("v0.3.x restore unavailable with this client; use litestream v0.3.x or a modern restore")
}

Type guard

func asV3Client(c litestream.ReplicaClient) (litestream.ReplicaClientV3, bool) {
    v3, ok := c.(litestream.ReplicaClientV3)
    return v3, ok
}

Try / catch

if err := r.RestoreV3(ctx, opt); err != nil {
    if strings.Contains(err.Error(), "does not support v0.3.x restore") {
        return fmt.Errorf("legacy restore unsupported; restore with litestream v0.3.x, then re-replicate: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling r.RestoreV3(ctx, opt) (or Restore against a legacy-path that selects V3) when the r.Client type assertion `client, ok := r.Client.(ReplicaClientV3)` fails — i.e., the storage backend lacks the V3 interface methods.

Common situations: Attempting to restore an old v0.3.x snapshot with a current config pointing at a v0.5+ replica client, using a custom storage backend that only implements the modern ReplicaClient interface, mixing old litestream data directories with new client types.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06). Data as JSON: /api/errors/3c3d769f17012400. Report an issue: GitHub.