{"record":{"id":"5ecd4cad84fe0109","repo":"t8y2/dbx","slug":"failed-to-migrate-json-data","errorCode":null,"errorMessage":"Failed to migrate JSON data","messagePattern":"Failed to migrate JSON data","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/dbx-web/src/main.rs","lineNumber":305,"sourceCode":"        .with_env_filter(\n            tracing_subscriber::EnvFilter::try_from_default_env()\n                .unwrap_or_else(|_| \"dbx_web=info,tower_http=info\".parse().unwrap()),\n        )\n        .init();\n\n    rustls::crypto::aws_lc_rs::default_provider().install_default().expect(\"Failed to install rustls crypto provider\");\n\n    // Data directory\n    let data_dir = std::env::var(\"DBX_DATA_DIR\").map(std::path::PathBuf::from).unwrap_or_else(|_| {\n        let home = std::env::var(\"HOME\").unwrap_or_else(|_| \".\".to_string());\n        std::path::PathBuf::from(home).join(\".dbx-web\")\n    });\n    std::fs::create_dir_all(&data_dir).expect(\"Failed to create data directory\");\n\n    let app_state = {\n        let db_path = data_dir.join(\"dbx.db\");\n        let storage = Storage::open(&db_path).await.expect(\"Failed to open storage\");\n        storage.migrate_from_json(&data_dir).await.expect(\"Failed to migrate JSON data\");\n\n        // Initialize core dialect registry and load external plugin dialects\n        register_core_dialects();\n        let registry = DialectRegistry::global();\n        let plugin_dirs = vec![data_dir.join(\"plugins\").join(\"dialects\")];\n        let load_result = DialectPluginLoader::scan_and_load(registry, &plugin_dirs);\n        log::info!(\n            \"Dialect plugins loaded: {} success, {} errors, {} skipped\",\n            load_result.loaded.len(),\n            load_result.errors.len(),\n            load_result.skipped.len()\n        );\n\n        // Start dialect YAML hot-reload watcher\n        let watch_dirs = plugin_dirs.clone();\n        tokio::spawn(async move {\n            if let Err(e) = DialectHotReload::run_forever(watch_dirs, DialectRegistry::global()).await {\n                log::error!(\"Dialect hot-reload watcher exited: {e}\");","sourceCodeStart":287,"sourceCodeEnd":323,"githubUrl":"https://github.com/t8y2/dbx/blob/c0390bff16418b651f4728520d99adf8ce48829a/crates/dbx-web/src/main.rs#L287-L323","documentation":"After opening storage, dbx-web runs storage.migrate_from_json(&data_dir) to import legacy JSON data into the database and expects success. A failure here halts startup because partially migrated data would leave the app in an inconsistent state.","triggerScenarios":"migrate_from_json fails when legacy JSON files in the data directory are malformed, unreadable, or fail schema parsing; the migration writes fail due to storage errors; or a previous migration left partial/corrupt state.","commonSituations":"Upgrading from an older file-based dbx-web version with hand-edited or truncated JSON files; JSON encoding issues after locale/manual edits; read-only mounts making legacy files unreadable or migration writes impossible.","solutions":["Validate/back up the legacy JSON files in the data directory, then fix or remove the malformed file causing the failure.","Temporarily move the legacy JSON files out of data_dir to skip migration and start fresh (legacy data will not be imported).","Restore the data directory from a backup and retry the upgrade.","Check storage writability and disk space so migration writes can complete.","Change the code to log the detailed migration error rather than a bare expect panic."],"exampleFix":"// before\nstorage.migrate_from_json(&data_dir).await.expect(\"Failed to migrate JSON data\");\n// after\nstorage.migrate_from_json(&data_dir).await\n    .unwrap_or_else(|e| panic!(\"Failed to migrate JSON data from {}: {e}\", data_dir.display()));","handlingStrategy":"validation","validationCode":"fn legacy_json_files_parse(data_dir: &std::path::Path) -> bool {\n    std::fs::read_dir(data_dir)\n        .map(|entries| entries.flatten()\n            .filter(|e| e.path().extension().map(|x| x == \"json\").unwrap_or(false))\n            .all(|e| std::fs::read_to_string(e.path()).map(|s| serde_json::from_str::<serde_json::Value>(&s).is_ok()).unwrap_or(false)))\n        .unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":"if let Err(e) = storage.migrate_from_json(&data_dir).await {\n    eprintln!(\"Failed to migrate JSON data from {}: {e}\", data_dir.display());\n    std::process::exit(1);\n}","preventionTips":["Back up the data directory before version upgrades that trigger migration.","Do not hand-edit legacy JSON files; validate them after manual changes.","Ensure the data directory is writable during migration.","Test the upgrade path on a copy of production data first."],"tags":["migration","rust","json","startup"],"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-14T05:17:10.506Z"}