maotoumao/MusicFree · warning

toast.resumeFail

Error message

toast.resumeFail

What it means

onResumeFromLocal in backupSetting.tsx restores a local backup; failures inside the restore callback and the outer try/catch both surface as Toast.warn(t('toast.resumeFail', {reason})). 'toast.resumeFail' is the i18n key for "restore failed", carrying the underlying exception message as reason.

Solutions

  1. Read the logged '恢复失败' (restore failed) error to see the exact cause (parse error vs IO error vs schema mismatch).
  2. Re-export a fresh backup and retry the restore.
  3. Validate the backup JSON structure before importing (check version fields and required keys).
  4. Upgrade the app if the backup was produced by a newer version, or add the toast.resumeFail key to locales so the reason is visible.

Example fix

// before
await resumeFromLocal(file);
// after
try {
  const raw = JSON.parse(fileContent);
  if (!raw || typeof raw !== 'object') throw new Error('invalid backup file');
  await resumeFromLocal(raw);
} catch (e) {
  Toast.warn(t('toast.resumeFail', { reason: e?.message ?? e }));
}
Defensive patterns

Strategy: try-catch

Validate before calling

const backup = JSON.parse(fileContent); // throws early on corrupt file
if (!backup || typeof backup !== 'object' || !Array.isArray(backup.musicShows)) {
  throw new Error('backup schema mismatch');
}

Type guard

function isValidBackup(b: unknown): b is BackupShape {
  return !!b && typeof b === 'object' && 'version' in (b as object);
}

Try / catch

try {
  await resumeFromLocal(file);
} catch (e) {
  errorLog('恢复失败', e);
  Toast.warn(t('toast.resumeFail', { reason: e?.message ?? e }));
}

Prevention

When it happens

Trigger: Restoring from a local backup file when: the backup JSON is corrupt or from an incompatible app version, file read fails (permission/moved file), or the import routine throws inside its callback or the awaited restore call throws.

Common situations: Selecting an old/edited backup file whose schema no longer matches; restoring a backup made on a newer app version; file picker returning a path the native layer cannot read; partial/corrupted file from an interrupted export.

Related errors


AI-assisted analysis of maotoumao/MusicFree@d118b18b3d (2026-08-30). Data as JSON: /api/errors/ee5f557e0d1093d1. Report an issue: GitHub.

Appendix: source

Thrown at src/pages/setting/settingTypes/backupSetting.tsx:107

                        Toast.success(t("toast.resumeSuccess"));
                        hideDialog();
                        resolve(true);
                    },
                    onCancel(hideDialog) {
                        hideDialog();
                        resolve(false);
                    },
                    onReject(reason, hideDialog) {
                        hideDialog();
                        resolve(false);
                        console.log(reason);
                        Toast.warn(t("toast.resumeFail", { reason: reason?.message ?? reason }));
                    },
                });
            });
        } catch (e: any) {
            errorLog("恢复失败", e);
            Toast.warn(t("toast.resumeFail", { reason: e?.message ?? e }));
        }
    }

    async function onResumeFromUrl() {
        showPanel("SimpleInput", {
            title: t("backupAndResume.resumeFromUrlDialogTitle"),
            placeholder: t("backupAndResume.resumeFromUrlDialogPlaceHolder"),
            maxLength: 1024,
            async onOk(text, closePanel) {
                try {
                    const url = text.trim();
                    if (url.endsWith(".json") || url.endsWith(".txt")) {
                        const raw = (await axios.get(text)).data;
                        await Backup.resume(raw, resumeMode);
                        Toast.success(t("toast.resumeSuccess"));
                        closePanel();
                    } else {
                        throw "无效的URL";

View on GitHub (pinned to d118b18b3d)