{"record":{"id":"23a36d9311da632b","repo":"rqlite/rqlite","slug":"failed-to-open-old-state-file-s-s","errorCode":null,"errorMessage":"failed to open old state file %s: %s","messagePattern":"failed to open old state file (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"snapshot/upgrader.go","lineNumber":118,"sourceCode":"\tif err := writeMeta(newSnapshotPath, oldMeta); err != nil {\n\t\treturn fmt.Errorf(\"failed to write new snapshot meta file to %s: %s\", newSnapshotPath, err)\n\t}\n\n\t// Ensure all file handles are closed before any directory is renamed or removed.\n\tif err := func() error {\n\t\t// Write SQLite database file into new snapshot dir.\n\t\tnewSqlitePath := filepath.Join(newTmpDir, oldMeta.ID+\".db\")\n\t\tnewSqliteFd, err := os.Create(newSqlitePath)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to create new SQLite file %s: %s\", newSqlitePath, err)\n\t\t}\n\t\tdefer newSqliteFd.Close()\n\n\t\t// Copy the old state file into the new generation directory.\n\t\toldStatePath := filepath.Join(old, oldMeta.ID, v7StateFile)\n\t\tstateFd, err := os.Open(oldStatePath)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to open old state file %s: %s\", oldStatePath, err)\n\t\t}\n\t\tdefer stateFd.Close()\n\t\tsz, err := fsutil.FileSize(oldStatePath)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to get size of old state file %s: %s\", oldStatePath, err)\n\t\t}\n\t\tlogger.Printf(\"successfully opened old state file at %s (%d bytes in size)\", oldStatePath, sz)\n\n\t\theaderLength := int64(16)\n\t\tif sz < headerLength {\n\t\t\treturn fmt.Errorf(\"old state file %s is too small to be valid\", oldStatePath)\n\t\t} else if sz == headerLength {\n\t\t\tlogger.Printf(\"old state file %s contains no database data, no data to upgrade\", oldStatePath)\n\t\t} else {\n\t\t\t// Skip past the header and length of the old state file.\n\t\t\tif _, err := stateFd.Seek(headerLength, 0); err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to seek to beginning of old SQLite data %s: %s\", oldStatePath, err)\n\t\t\t}","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/rqlite/rqlite/blob/7586a4d1bdbd9a5a80021664c5a863cd850adb60/snapshot/upgrader.go#L100-L136","documentation":"Upgrade7To8 found the newest v7 snapshot metadata but could not open its state file '<old>/<id>/state.bin' with os.Open. This means the v7 snapshot data referenced by the metadata is missing or unreadable — the meta.json survived but the state.bin did not. The upgrade aborts and the temp directory is cleaned up.","triggerScenarios":"os.Open(filepath.Join(old, oldMeta.ID, \"state.bin\")) fails: the state.bin file was deleted, the snapshot subdirectory is incomplete, or permissions deny read access.","commonSituations":"Crash or disk-full during a previous v7 snapshot write left a snapshot directory with meta.json but no/partial state.bin; manual cleanup scripts deleted state.bin files; backups restored without data files; permissions changed after a user migration.","solutions":["Inspect '<old>/<id>/' — if state.bin is missing or truncated, delete that incomplete snapshot directory and retry, or restore from backup.","Restore the node's data directory (or use /boot) from a good backup, since the referenced snapshot data is unrecoverable.","Fix read permissions on the snapshot subdirectory and state.bin for the rqlited process user.","If other valid v7 snapshots exist, ensure the newest one is the complete one; consider removing only the broken snapshot directory so upgrade picks a complete snapshot."],"exampleFix":"// before\n//  rsnapshots/v7/<id>/meta.json exists, state.bin missing\n// after\nrm -rf /path/node/data/rsnapshots/v7/<id-without-state.bin>\n# restart rqlited; upgrade proceeds with remaining complete snapshots or clean path","handlingStrategy":"validation","validationCode":"// Go: verify the newest v7 snapshot's state file exists before upgrading\nfunc newestV7StateFilePresent(old string) (bool, error) {\n\tentries, err := os.ReadDir(old)\n\tif err != nil { return false, err }\n\tfor _, e := range entries {\n\t\tif e.IsDir() && fsutil.FileExists(filepath.Join(old, e.Name(), \"meta.json\")) {\n\t\t\treturn fsutil.FileExists(filepath.Join(old, e.Name(), \"state.bin\")), nil\n\t\t}\n\t}\n\treturn false, nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never run cleanup scripts that match on files like state.bin inside rsnapshots.","After disk-full incidents, assume the newest snapshot may be incomplete and verify its files.","Back up and restore the entire rsnapshots tree atomically, not file-by-file.","Verify backup restores include both meta.json and state.bin for v7 data."],"tags":["filesystem","data-corruption","snapshot-migration","missing-file"],"backgroundTag":"snapshot-data-file-missing","analyzedSha":"7586a4d1bdbd9a5a80021664c5a863cd850adb60","analyzedAt":"2026-09-03T07:03:02.260Z","contentChangedAt":"2026-09-03T07:03:02.260Z","schemaVersion":2},"datasetVersion":"2026-09-10T12:17:11.382Z"}