k3s-io/k3s · critical
failed to migrate content from sqlite to etcd: %w
Error message
failed to migrate content from sqlite to etcd: %w
What it means
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.
Source
Thrown at pkg/etcd/etcd.go:911
return ip, nil
}
// newCluster calls cluster to start up etcd for a new cluster, with no existing members.
// Existing data from sqlite is migrated over, if present.
func (e *ETCD) newCluster(ctx context.Context, wg *sync.WaitGroup, reset bool) error {
logrus.Infof("Starting etcd for new cluster, cluster-reset=%v", reset)
err := e.cluster(ctx, wg, reset, executor.InitialOptions{
AdvertisePeerURL: e.peerURL(),
Cluster: fmt.Sprintf("%s=%s", e.name, e.peerURL()),
State: "new",
})
if err != nil {
return err
}
if !reset {
if err := e.migrateFromSQLite(ctx); err != nil {
return fmt.Errorf("failed to migrate content from sqlite to etcd: %w", err)
}
}
return nil
}
func (e *ETCD) migrateFromSQLite(ctx context.Context) error {
_, err := os.Stat(sqliteFile(e.config))
if os.IsNotExist(err) {
return nil
} else if err != nil {
return err
}
logrus.Infof("Migrating content from sqlite to etcd")
ctx, cancel := context.WithCancel(ctx)
defer cancel()
View on GitHub (pinned to 6ba341e396)
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.
Example fix
# before (migration fails or db is suspect) k3s server --cluster-init # after (clean HA bootstrap from a good snapshot) k3s server --cluster-init # first start: create empty etcd cluster k3s server --cluster-reset \ --cluster-reset-restore-path=/backups/etcd-snapshot.db # restore data into it
Defensive patterns
Strategy: try-catch
Validate before calling
// Before enabling --cluster-init on an existing node, sanity-check the SQLite db:
if _, err := os.Stat(filepath.Join(dataDir, "server", "db", "state.db")); err == nil {
out, err := exec.Command("sqlite3", filepath.Join(dataDir, "server", "db", "state.db"), "PRAGMA integrity_check;").CombinedOutput()
if err != nil || strings.TrimSpace(string(out)) != "ok" {
log.Fatalf("state.db not healthy - restore from snapshot instead of migrating: %v %s", err, out)
}
} Try / catch
// Wrap and inspect the migration error chain; fall back to snapshot restore on corruption:
if err := server.Start(ctx); err != nil {
var migErr *fmt.WrapError // illustrative: check message prefix instead
if strings.Contains(err.Error(), "failed to migrate content from sqlite to etcd") {
log.Fatal("migration failed - preserve data dir, then restore from an etcd snapshot with --cluster-reset-restore-path")
}
log.Fatal(err)
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- etcd datastore disabled
- found multiple bootstrap keys in storage
- invalid flag use; --server is required with --disable-etcd
- invalid flag use; cannot use --disable-etcd with --datastore
- no bootstrap data found in datastore - check server token va
AI-assisted analysis of k3s-io/k3s@6ba341e396 (2026-08-15).
Data as JSON: /api/errors/9c56f0c091e737a8.
Report an issue: GitHub.