{"record":{"id":"9c56f0c091e737a8","repo":"k3s-io/k3s","slug":"failed-to-migrate-content-from-sqlite-to-etcd-w","errorCode":null,"errorMessage":"failed to migrate content from sqlite to etcd: %w","messagePattern":"failed to migrate content from sqlite to etcd: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"pkg/etcd/etcd.go","lineNumber":911,"sourceCode":"\n\treturn ip, nil\n}\n\n// newCluster calls cluster to start up etcd for a new cluster, with no existing members.\n// Existing data from sqlite is migrated over, if present.\nfunc (e *ETCD) newCluster(ctx context.Context, wg *sync.WaitGroup, reset bool) error {\n\tlogrus.Infof(\"Starting etcd for new cluster, cluster-reset=%v\", reset)\n\terr := e.cluster(ctx, wg, reset, executor.InitialOptions{\n\t\tAdvertisePeerURL: e.peerURL(),\n\t\tCluster:          fmt.Sprintf(\"%s=%s\", e.name, e.peerURL()),\n\t\tState:            \"new\",\n\t})\n\tif err != nil {\n\t\treturn err\n\t}\n\tif !reset {\n\t\tif err := e.migrateFromSQLite(ctx); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to migrate content from sqlite to etcd: %w\", err)\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (e *ETCD) migrateFromSQLite(ctx context.Context) error {\n\t_, err := os.Stat(sqliteFile(e.config))\n\tif os.IsNotExist(err) {\n\t\treturn nil\n\t} else if err != nil {\n\t\treturn err\n\t}\n\n\tlogrus.Infof(\"Migrating content from sqlite to etcd\")\n\n\tctx, cancel := context.WithCancel(ctx)\n\tdefer cancel()\n","sourceCodeStart":893,"sourceCodeEnd":929,"githubUrl":"https://github.com/k3s-io/k3s/blob/6ba341e396edc16b8dcae978a7c5e3ac7ee5606e/pkg/etcd/etcd.go#L893-L929","documentation":"When embedded etcd is initialized without reset (i.e. `--cluster-init` on a node whose SQLite datastore file exists), newCluster bootstraps a fresh etcd cluster and then migrateFromSQLite copies the existing SQLite data through kine into etcd. This wrapping error means that migration failed; the underlying cause is in the %w chain. This is the standalone-SQLite-to-HA-etcd upgrade path.","triggerScenarios":"Running `k3s server --cluster-init` on a node with an existing <data-dir>/server/db/state.db (pkg/etcd/etcd.go:902-912). Migration fails if the SQLite db is corrupt/unreadable, kine cannot open it, etcd rejects the writes, or a previous half-completed migration left inconsistent state.","commonSituations":"Converting a single-node SQLite k3s to embedded-etcd HA; retrying --cluster-init after a first failed attempt; very old k3s versions with schema drift; state.db damaged by an unclean shutdown.","solutions":["Read the wrapped cause in the log line (the %w suffix) - it distinguishes SQLite corruption from etcd/kine connectivity issues.","Back up the whole data dir, then restore from an etcd snapshot instead of migrating: `k3s server --cluster-reset --cluster-reset-restore-path=<snapshot.db>` after starting --cluster-init once.","Verify the SQLite db is healthy before retrying: `sqlite3 /var/lib/rancher/k3s/server/db/state.db 'PRAGMA integrity_check;'` - if corrupt, restore from backup or snapshot rather than retrying migration.","Ensure you only run --cluster-init once per node and that all servers converge on the same initial cluster."],"exampleFix":"# before (migration fails or db is suspect)\nk3s server --cluster-init\n\n# after (clean HA bootstrap from a good snapshot)\nk3s server --cluster-init                      # first start: create empty etcd cluster\nk3s server --cluster-reset \\\n  --cluster-reset-restore-path=/backups/etcd-snapshot.db   # restore data into it","handlingStrategy":"try-catch","validationCode":"// Before enabling --cluster-init on an existing node, sanity-check the SQLite db:\nif _, err := os.Stat(filepath.Join(dataDir, \"server\", \"db\", \"state.db\")); err == nil {\n    out, err := exec.Command(\"sqlite3\", filepath.Join(dataDir, \"server\", \"db\", \"state.db\"), \"PRAGMA integrity_check;\").CombinedOutput()\n    if err != nil || strings.TrimSpace(string(out)) != \"ok\" {\n        log.Fatalf(\"state.db not healthy - restore from snapshot instead of migrating: %v %s\", err, out)\n    }\n}","typeGuard":null,"tryCatchPattern":"// Wrap and inspect the migration error chain; fall back to snapshot restore on corruption:\nif err := server.Start(ctx); err != nil {\n    var migErr *fmt.WrapError // illustrative: check message prefix instead\n    if strings.Contains(err.Error(), \"failed to migrate content from sqlite to etcd\") {\n        log.Fatal(\"migration failed - preserve data dir, then restore from an etcd snapshot with --cluster-reset-restore-path\")\n    }\n    log.Fatal(err)\n}","preventionTips":["Always back up the full data dir before first --cluster-init.","Do the SQLite-to-etcd conversion once, on a tested upgrade path, at a quiet time.","Keep regular etcd snapshots once on etcd so migration is never the only recovery path."],"tags":["etcd","sqlite","migration","cluster-init","ha","k3s"],"backgroundTag":null,"analyzedSha":"6ba341e396edc16b8dcae978a7c5e3ac7ee5606e","analyzedAt":"2026-08-15T16:27:54.286Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}