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
- 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.
- 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.
- 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
- Wrap cluster-reset automation in a pre-flight check for the snapshot path.
- Keep a documented, tested restore command per environment so the path flag is never improvised.
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
- invalid flag use; --cluster-reset required with --cluster-re
- etcd-s3-timeout must be greater than 0s
- invalid flag use; --server is required with --disable-etcd
- invalid flag use; cannot use --disable-etcd with --datastore
- cannot perform cluster-reset while server URL is set - remov
AI-assisted analysis of k3s-io/k3s@6ba341e396 (2026-08-15).
Data as JSON: /api/errors/734b3f3f34b45748.
Report an issue: GitHub.