k3s-io/k3s · error

no etcd restore path was specified

Error message

no etcd restore path was specified

What it means

Restore performs an offline etcd restore from a snapshot and requires config.ClusterResetRestorePath to point at the snapshot file. When that field is empty the function refuses before touching any state, so nothing is moved or renamed.

Source

Thrown at pkg/etcd/etcd.go:1516

		if !member.IsLearner && !isSelf {
			if isPreferred {
				clientURLs = append(member.ClientURLs, clientURLs...)
			} else {
				clientURLs = append(clientURLs, member.ClientURLs...)
			}
		}
	}
	return clientURLs, memberList, nil
}

// Restore performs a restore of the ETCD datastore from
// the given snapshot path. This operation exists upon
// completion.
func (e *ETCD) Restore(ctx context.Context) error {
	// check the old etcd data dir
	oldDataDir := dbDir(e.config) + "-old-" + strconv.Itoa(int(time.Now().Unix()))
	if e.config.ClusterResetRestorePath == "" {
		return errors.New("no etcd restore path was specified")
	}
	// make sure snapshot exists before restoration
	if _, err := os.Stat(e.config.ClusterResetRestorePath); err != nil {
		return err
	}
	// Restore is an offline operation, so create a logger for it instead of borrowing one from
	// the datastore client. Do it before anything is moved, so that we fail early.
	logger, err := logutil.CreateDefaultZapLogger(zapcore.InfoLevel)
	if err != nil {
		return err
	}

	var restorePath string
	if strings.HasSuffix(e.config.ClusterResetRestorePath, snapshot.CompressedExtension) {
		dir, err := snapshotDir(e.config, true)
		if err != nil {
			return errors.WithMessage(err, "failed to get the snapshot dir")
		}

View on GitHub (pinned to 6ba341e396)

Solutions

  1. Pass the snapshot path explicitly: k3s server --cluster-reset --cluster-reset-restore-path=/var/lib/rancher/k3s/server/db/snapshots/etcd-snapshot-<date>-<tz>.zip.
  2. If the snapshot lives in S3, add the --etcd-s3-* flags (or config secret) so the restore can fetch it, and keep --cluster-reset-restore-path set to the snapshot name/path.
  3. Verify the snapshot file exists and is readable before retrying; the next check os.Stat will fail otherwise.

Example fix

# before
k3s server --cluster-reset
# after
k3s server --cluster-reset --cluster-reset-restore-path=/var/lib/rancher/k3s/server/db/snapshots/etcd-snapshot-20260801T000000Z.zip
Defensive patterns

Strategy: validation

Validate before calling

if cfg.ClusterReset && cfg.ClusterResetRestorePath == "" {
    return errors.New("cluster-reset requested without a restore path; pass --cluster-reset-restore-path")
}

Try / catch

if err := e.Restore(ctx); err != nil {
    if strings.Contains(err.Error(), "no etcd restore path was specified") {
        // operator error: fix flags and re-run; nothing was modified yet
    }
    return err
}

Prevention

When it happens

Trigger: Running a cluster-reset flow (ETCD.Restore) without passing --cluster-reset-restore-path, e.g. 'k3s server --cluster-reset' with S3 options but no snapshot path, or calling Restore programmatically on a config where ClusterResetRestorePath was never set.

Common situations: Operators running --cluster-reset expecting a local restore but forgetting the snapshot argument; automation that sets --cluster-reset only; passing an S3 snapshot name where a local path is expected (S3 snapshots must be downloaded first or referenced via the s3:// flow).

Related errors


AI-assisted analysis of k3s-io/k3s@6ba341e396 (2026-08-15). Data as JSON: /api/errors/734b3f3f34b45748. Report an issue: GitHub.