{"record":{"id":"e40fa4036f167adc","repo":"t8y2/dbx","slug":"failed-to-migrate-json-data-e40fa4","errorCode":null,"errorMessage":"Failed to migrate JSON data","messagePattern":"Failed to migrate JSON data","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/src/lib.rs","lineNumber":1514,"sourceCode":"            let data_dir = data_dir_resolution.data_dir.clone();\n            std::fs::create_dir_all(&data_dir).expect(\"Failed to create data dir\");\n            let data_dir_mode = startup_data_dir_mode(&data_dir_resolution.mode);\n            append_startup_probe(format!(\"data dir ready mode={data_dir_mode}\"));\n            let alternative_data_dir = data_dir::alternative_data_dir(&data_dir_resolution);\n            match maybe_import_user_data_db(&data_dir, alternative_data_dir.as_deref()) {\n                Ok(result) => eprintln!(\"[STARTUP] data db fallback import: {result:?}\"),\n                Err(err) => eprintln!(\"[STARTUP] data db fallback import failed: {err}\"),\n            }\n            let db_path = data_dir.join(\"dbx.db\");\n\n            let t = Instant::now();\n            append_startup_probe(format!(\"opening storage file=dbx.db data_dir_mode={data_dir_mode}\"));\n            let storage = tauri::async_runtime::block_on(async {\n                let s = Storage::open(&db_path).await.expect(\"Failed to open storage\");\n                eprintln!(\"[STARTUP]   Storage::open in {:?}\", t.elapsed());\n                append_startup_probe(format!(\"storage opened in {:?}\", t.elapsed()));\n                let t2 = Instant::now();\n                s.migrate_from_json(&data_dir).await.expect(\"Failed to migrate JSON data\");\n                eprintln!(\"[STARTUP]   migrate_from_json in {:?}\", t2.elapsed());\n                append_startup_probe(format!(\"json migration completed in {:?}\", t2.elapsed()));\n                s\n            });\n            let desktop_settings = tauri::async_runtime::block_on(storage.load_desktop_settings()).unwrap_or_default();\n            app.handle().plugin(\n                tauri_plugin_log::Builder::default()\n                    .timezone_strategy(tauri_plugin_log::TimezoneStrategy::UseLocal)\n                    .format(|out, message, record| {\n                        out.finish(format_args!(\n                            \"[{}][{}][{}] {}\",\n                            chrono::Local::now().format(\"%Y-%m-%d][%H:%M:%S%.3f\"),\n                            record.level(),\n                            record.target(),\n                            message\n                        ));\n                    })\n                    .level(log::LevelFilter::Debug)","sourceCodeStart":1496,"sourceCodeEnd":1532,"githubUrl":"https://github.com/t8y2/dbx/blob/c0390bff16418b651f4728520d99adf8ce48829a/src-tauri/src/lib.rs#L1496-L1532","documentation":"After opening storage, the app runs s.migrate_from_json(&data_dir) to import legacy JSON files into the new database and panics if migration fails. Failures stem from malformed or unreadable legacy JSON files or database write errors during import.","triggerScenarios":"migrate_from_json at lib.rs:1514 failing when legacy JSON files in the data dir are corrupt, have unsupported schema versions, or the newly opened storage rejects writes (permissions, constraints, disk full).","commonSituations":"Users upgrading from the JSON-based version with hand-edited or partially synced JSON files; interrupted previous migration leaving partial state; JSON encoding incompatibilities after a version change.","solutions":["Back up and move the offending JSON files out of the data dir so the app can start with an empty database.","Inspect the legacy JSON files with a validator to find malformed entries and fix or remove them.","Downgrade to the previous app version to export clean data, or handle the Result with a skip-and-log policy for bad records instead of expect()."],"exampleFix":"// before\ns.migrate_from_json(&data_dir).await.expect(\"Failed to migrate JSON data\");\n// after\nif let Err(e) = s.migrate_from_json(&data_dir).await {\n    eprintln!(\"[STARTUP] JSON migration failed (continuing with empty db): {e}\");\n}","handlingStrategy":"try-catch","validationCode":"// Rust: validate legacy JSON before migrating\nfn json_files_parse(dir: &std::path::Path) -> Vec<std::path::PathBuf> {\n    std::fs::read_dir(dir).into_iter().flatten()\n        .filter_map(|e| e.ok().map(|e| e.path()))\n        .filter(|p| p.extension().map_or(false, |x| x == \"json\"))\n        .filter(|p| std::fs::read_to_string(p)\n            .map(|s| serde_json::from_str::<serde_json::Value>(&s).is_err())\n            .unwrap_or(true))\n        .collect()\n}","typeGuard":null,"tryCatchPattern":"match s.migrate_from_json(&data_dir).await {\n    Ok(()) => {}\n    Err(e) => eprintln!(\"[STARTUP] JSON migration failed, continuing: {e}\"),\n}","preventionTips":["Validate legacy JSON files (schema version + serde parse) before migrating.","Make migration resumable/idempotent so an interrupted run can complete.","Log and skip bad records instead of failing the whole migration; archive unparseable files."],"tags":["rust","migration","json","database"],"backgroundTag":"data-migration-failed","analyzedSha":"c0390bff16418b651f4728520d99adf8ce48829a","analyzedAt":"2026-09-05T23:05:10.900Z","contentChangedAt":"2026-09-05T23:05:10.900Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}