{"record":{"id":"7d970f3692f1c022","repo":"maotoumao/MusicFree","slug":"toast-backupfail","errorCode":null,"errorMessage":"toast.backupFail","messagePattern":"toast\\.backupFail","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/pages/setting/settingTypes/backupSetting.tsx","lineNumber":62,"sourceCode":"                        promise: writeInChunks(\r\n                            `${folder}${folder?.endsWith(\"/\") ? \"\" : \"/\"\r\n                            }backup.json`,\r\n                            raw,\r\n                        ),\r\n                        onResolve(_, hideDialog) {\r\n                            Toast.success(t(\"toast.backupSuccess\"));\r\n                            hideDialog();\r\n                            resolve(true);\r\n                        },\r\n                        onCancel(hideDialog) {\r\n                            hideDialog();\r\n                            resolve(false);\r\n                        },\r\n                        onReject(reason, hideDialog) {\r\n                            hideDialog();\r\n                            resolve(false);\r\n                            console.log(reason);\r\n                            Toast.warn(t(\"toast.backupFail\", { reason: reason?.message ?? reason }));\r\n                        },\r\n                    });\r\n                });\r\n            },\r\n        });\r\n    };\r\n\r\n    async function onResumeFromLocal() {\r\n        try {\r\n            const pickResult = await getDocumentAsync({\r\n                copyToCacheDirectory: true,\r\n                type: \"application/json\",\r\n            });\r\n            if (pickResult.canceled) {\r\n                return;\r\n            }\r\n            const result = await readAsStringAsync(pickResult.assets[0].uri);\r\n            return new Promise(resolve => {\r","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/maotoumao/MusicFree/blob/d118b18b3d0c904400f7eea7bf99c0ceec6c1aee/src/pages/setting/settingTypes/backupSetting.tsx#L44-L80","documentation":"A localized warning toast: \"Backup failed: {reason}\" (zh: 备份失败). Shown when the WebDAV backup operation's onReject callback fires, i.e. the backup promise was rejected. The raw rejection reason is interpolated into the message and logged to console.","triggerScenarios":"Calling the backup action whose dialog provider invokes onReject(reason, hideDialog); the underlying backup routine (e.g. WebDAV upload or storage write) rejects with an Error or string reason, hideDialog() closes the dialog and Toast.warn renders the interpolated failure message.","commonSituations":"WebDAV server unreachable or wrong URL/credentials during backup; storage permission denied; backup file serialization throws; network timeout mid-upload.","solutions":["Read the {reason} in the toast / console.log output: it contains the underlying Error message to act on.","Verify WebDAV settings (webdav.url, webdav.username, webdav.password) in the app's WebDAV Settings before retrying backup.","Check network connectivity and that the WebDAV server is reachable and accepting writes.","If reason is an Error, inspect reason.message rather than the object; adjust the caller to normalize `reason?.message ?? reason`.","Retry the backup after fixing the cause; the failure is recoverable."],"exampleFix":"// before\nToast.warn(t(\"toast.backupFail\", { reason: reason?.message ?? reason }));\n// after\nconst detail = reason instanceof Error ? reason.message : String(reason);\nerrorLog(\"备份失败\", reason);\nToast.warn(t(\"toast.backupFail\", { reason: detail }));","handlingStrategy":"try-catch","validationCode":"const url = Config.getConfig(\"webdav.url\");\nconst username = Config.getConfig(\"webdav.username\");\nconst password = Config.getConfig(\"webdav.password\");\nif (!(url && username && password)) {\n    Toast.warn(t(\"toast.resumePreCheckFailed\"));\n    return; // avoid starting a backup that will reject\n}","typeGuard":"function hasReason(reason: unknown): reason is { message: string } {\n    return typeof reason === \"object\" && reason !== null &&\n        \"message\" in reason && typeof (reason as any).message === \"string\";\n}","tryCatchPattern":"try {\n    await runBackup();\n} catch (reason: any) {\n    console.log(reason);\n    Toast.warn(t(\"toast.backupFail\", { reason: reason?.message ?? String(reason) }));\n}","preventionTips":["Validate WebDAV URL/credentials before launching backup.","Log the full rejection object, not just the toast interpolation, to keep the root cause.","Distinguish user-facing messages from Error.message when building the toast text.","Test backup against the real WebDAV server after any credential or URL change."],"tags":["i18n","backup","webdav","ui-toast"],"backgroundTag":"backup-operation-failed","analyzedSha":"d118b18b3d0c904400f7eea7bf99c0ceec6c1aee","analyzedAt":"2026-08-30T11:49:12.932Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}