{"record":{"id":"734b3f3f34b45748","repo":"k3s-io/k3s","slug":"no-etcd-restore-path-was-specified","errorCode":null,"errorMessage":"no etcd restore path was specified","messagePattern":"no etcd restore path was specified","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/etcd/etcd.go","lineNumber":1516,"sourceCode":"\t\tif !member.IsLearner && !isSelf {\n\t\t\tif isPreferred {\n\t\t\t\tclientURLs = append(member.ClientURLs, clientURLs...)\n\t\t\t} else {\n\t\t\t\tclientURLs = append(clientURLs, member.ClientURLs...)\n\t\t\t}\n\t\t}\n\t}\n\treturn clientURLs, memberList, nil\n}\n\n// Restore performs a restore of the ETCD datastore from\n// the given snapshot path. This operation exists upon\n// completion.\nfunc (e *ETCD) Restore(ctx context.Context) error {\n\t// check the old etcd data dir\n\toldDataDir := dbDir(e.config) + \"-old-\" + strconv.Itoa(int(time.Now().Unix()))\n\tif e.config.ClusterResetRestorePath == \"\" {\n\t\treturn errors.New(\"no etcd restore path was specified\")\n\t}\n\t// make sure snapshot exists before restoration\n\tif _, err := os.Stat(e.config.ClusterResetRestorePath); err != nil {\n\t\treturn err\n\t}\n\t// Restore is an offline operation, so create a logger for it instead of borrowing one from\n\t// the datastore client. Do it before anything is moved, so that we fail early.\n\tlogger, err := logutil.CreateDefaultZapLogger(zapcore.InfoLevel)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tvar restorePath string\n\tif strings.HasSuffix(e.config.ClusterResetRestorePath, snapshot.CompressedExtension) {\n\t\tdir, err := snapshotDir(e.config, true)\n\t\tif err != nil {\n\t\t\treturn errors.WithMessage(err, \"failed to get the snapshot dir\")\n\t\t}","sourceCodeStart":1498,"sourceCodeEnd":1534,"githubUrl":"https://github.com/k3s-io/k3s/blob/6ba341e396edc16b8dcae978a7c5e3ac7ee5606e/pkg/etcd/etcd.go#L1498-L1534","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","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."],"exampleFix":"# before\nk3s server --cluster-reset\n# after\nk3s server --cluster-reset --cluster-reset-restore-path=/var/lib/rancher/k3s/server/db/snapshots/etcd-snapshot-20260801T000000Z.zip","handlingStrategy":"validation","validationCode":"if cfg.ClusterReset && cfg.ClusterResetRestorePath == \"\" {\n    return errors.New(\"cluster-reset requested without a restore path; pass --cluster-reset-restore-path\")\n}","typeGuard":null,"tryCatchPattern":"if err := e.Restore(ctx); err != nil {\n    if strings.Contains(err.Error(), \"no etcd restore path was specified\") {\n        // operator error: fix flags and re-run; nothing was modified yet\n    }\n    return err\n}","preventionTips":["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."],"tags":["etcd","restore","configuration"],"backgroundTag":null,"analyzedSha":"6ba341e396edc16b8dcae978a7c5e3ac7ee5606e","analyzedAt":"2026-08-15T16:27:54.286Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}