maotoumao/MusicFree · info
升级失败
Error message
升级失败
What it means
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.
Source
Thrown at src/core/musicSheet/migrate.ts:30
// 原来的musicSheets
const musicSheets: IMusic.IMusicSheetItemBase[] = await oldGetStorage(
"music-sheets",
);
if (!musicSheets) {
appMeta.setMusicSheetVersion(1);
return;
}
await storage.setSheets(musicSheets);
await AsyncStorage.removeItem("music-sheets");
for (let sheet of musicSheets) {
const musicList = await oldGetStorage(sheet.id);
await storage.setMusicList(sheet.id, musicList);
await AsyncStorage.removeItem(sheet.id);
}
appMeta.setMusicSheetVersion(1);
} catch (e) {
console.warn("升级失败", e);
}
}
export const migrateV2 = {
migrate(sheetId: string, musicItems: IMusic.IMusicItem[]) {
const dbUpdated = appMeta.musicSheetVersion === 2;
if (dbUpdated) {
return;
}
let dirty = false;
const now = Date.now();
musicItems.forEach((it, index) => {
if (!it.$timestamp || it.$sortIndex === undefined) {
it.$timestamp = now;
it.$sortIndex = index;
dirty = true;
}
});
View on GitHub (pinned to d118b18b3d)
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.
Example fix
// before
} catch (e) {
console.warn("升级失败", e);
}
// after
} catch (e) {
console.warn("升级失败", e);
Toast.warn(t("toast.migrateFail", { reason: e?.message ?? e }));
} Defensive patterns
Strategy: retry
Validate before calling
const raw = await AsyncStorage.getItem(sheet.id);
if (!raw) { appMeta.setMusicSheetVersion(1); return; } // nothing to migrate
JSON.parse(raw); // fail fast on corrupt data before touching new storage Try / catch
try {
await migrateSheets();
} catch (e) {
console.warn('升级失败', e);
// version not bumped -> next launch retries automatically
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
AI-assisted analysis of maotoumao/MusicFree@d118b18b3d (2026-08-30).
Data as JSON: /api/errors/8cca0254ebf44873.
Report an issue: GitHub.