{"record":{"id":"8cca0254ebf44873","repo":"maotoumao/MusicFree","slug":"error-8cca02","errorCode":null,"errorMessage":"升级失败","messagePattern":"升级失败","errorType":"console","errorClass":null,"httpStatus":null,"severity":"info","filePath":"src/core/musicSheet/migrate.ts","lineNumber":30,"sourceCode":"        // 原来的musicSheets\r\n        const musicSheets: IMusic.IMusicSheetItemBase[] = await oldGetStorage(\r\n            \"music-sheets\",\r\n        );\r\n        if (!musicSheets) {\r\n            appMeta.setMusicSheetVersion(1);\r\n            return;\r\n        }\r\n\r\n        await storage.setSheets(musicSheets);\r\n        await AsyncStorage.removeItem(\"music-sheets\");\r\n        for (let sheet of musicSheets) {\r\n            const musicList = await oldGetStorage(sheet.id);\r\n            await storage.setMusicList(sheet.id, musicList);\r\n            await AsyncStorage.removeItem(sheet.id);\r\n        }\r\n        appMeta.setMusicSheetVersion(1);\r\n    } catch (e) {\r\n        console.warn(\"升级失败\", e);\r\n    }\r\n}\r\n\r\nexport const migrateV2 = {\r\n    migrate(sheetId: string, musicItems: IMusic.IMusicItem[]) {\r\n        const dbUpdated = appMeta.musicSheetVersion === 2;\r\n        if (dbUpdated) {\r\n            return;\r\n        }\r\n        let dirty = false;\r\n        const now = Date.now();\r\n        musicItems.forEach((it, index) => {\r\n            if (!it.$timestamp || it.$sortIndex === undefined) {\r\n                it.$timestamp = now;\r\n                it.$sortIndex = index;\r\n                dirty = true;\r\n            }\r\n        });\r","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/maotoumao/MusicFree/blob/d118b18b3d0c904400f7eea7bf99c0ceec6c1aee/src/core/musicSheet/migrate.ts#L12-L48","documentation":"migrate in src/core/musicSheet/migrate.ts moves old music-sheet data from AsyncStorage into the new storage layer and bumps musicSheetVersion to 1; failures are caught and only console.warn('升级失败', e) (\"upgrade failed\") is emitted — the message is a log, not a thrown error. A swallowed failure leaves sheets unmigrated and the version unbumped.","triggerScenarios":"Running the app after an upgrade where AsyncStorage.getItem for a sheet id fails, storage.setMusicList rejects (DB locked/corrupt), or AsyncStorage.removeItem fails — any rejection in the per-sheet loop triggers the catch.","commonSituations":"Upgrading from a very old version with large sheets (quota/serialization issues); corrupted AsyncStorage after a failed update; concurrent migration attempts; app killed mid-migration leaving partial state.","solutions":["Reproduce with console output: the warn includes the original error — fix the underlying storage failure it names.","Because appMeta.setMusicSheetVersion(1) only runs on success, relaunching the app re-attempts migration once the storage issue is fixed.","If a specific sheet is corrupt, wrap per-sheet migration in its own try/catch so one bad sheet doesn't stop the rest.","Back up AsyncStorage data before upgrading if sheets are valuable."],"exampleFix":"// before\n} catch (e) {\n  console.warn(\"升级失败\", e);\n}\n// after\n} catch (e) {\n  console.warn(\"升级失败\", e);\n  Toast.warn(t(\"toast.migrateFail\", { reason: e?.message ?? e }));\n}","handlingStrategy":"retry","validationCode":"const raw = await AsyncStorage.getItem(sheet.id);\nif (!raw) { appMeta.setMusicSheetVersion(1); return; } // nothing to migrate\nJSON.parse(raw); // fail fast on corrupt data before touching new storage","typeGuard":null,"tryCatchPattern":"try {\n  await migrateSheets();\n} catch (e) {\n  console.warn('升级失败', e);\n  // version not bumped -> next launch retries automatically\n}","preventionTips":["Scope try/catch per sheet so one corrupt sheet doesn't block the rest.","Only bump musicSheetVersion after all sheets succeed (current behavior — keep it).","Back up AsyncStorage before performing migrations.","Test migrations against real legacy data before shipping an upgrade."],"tags":["migration","storage","asyncstorage","upgrade","swallowed-error"],"backgroundTag":"storage-migration-failed","analyzedSha":"d118b18b3d0c904400f7eea7bf99c0ceec6c1aee","analyzedAt":"2026-08-30T11:49:12.932Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}