fix(backup): improve error messages to distinguish EBUSY from format errors

Closes #12160

**Changes**:
- Enhanced error handling in BackupService.ts (restore, restoreFromWebdav, restoreFromLocal)
- Added specific error messages for EBUSY (file locked) and ENOENT (file not found)
- Added i18n support for new error messages in en-us.json and zh-cn.json

**Impact**:
Users will now see accurate error messages:
- EBUSY errors → "Cannot restore: Some files are in use. Please close all knowledge bases or restart the app and try again."
- ENOENT errors → "Backup file not found or is corrupted"
- JSON errors → "Backup file format error"
- Other errors → Detailed error message for debugging

**Technical Details**:
- Distinguishes error codes (EBUSY, ENOENT) and message content
- Provides clear user guidance instead of misleading "file format error"
- Step 1 of phased fix plan for #12160
This commit is contained in:
GeorgeDong32 2025-12-27 22:16:11 +08:00 committed by George·Dong
parent 9414f13f6d
commit c06f93aeda
No known key found for this signature in database
3 changed files with 55 additions and 8 deletions

View File

@ -1309,7 +1309,9 @@
"availableProviders": "Available Providers",
"availableTools": "Available Tools",
"backup": {
"file_format": "Backup file format error"
"file_format": "Backup file format error",
"file_locked": "Cannot restore: Some files are in use. Please close all knowledge bases or restart the app and try again.",
"file_not_found": "Backup file not found or is corrupted"
},
"base64DataTruncated": "Base64 image data truncated, size",
"boundary": {

View File

@ -1309,7 +1309,9 @@
"availableProviders": "可用提供商",
"availableTools": "可用工具",
"backup": {
"file_format": "备份文件格式错误"
"file_format": "备份文件格式错误",
"file_locked": "无法恢复:某些文件正在使用中。请关闭所有知识库或重启应用后重试。",
"file_not_found": "备份文件未找到或已损坏"
},
"base64DataTruncated": "Base64 图片数据已截断,大小",
"boundary": {

View File

@ -100,9 +100,23 @@ export async function restore() {
source: 'backup',
channel: 'system'
})
} catch (error) {
} catch (error: any) {
logger.error('restore: Error restoring backup file:', error as Error)
window.toast.error(i18n.t('error.backup.file_format'))
// Distinguish different error types for better user experience
const errorCode = error.code || ''
const errorMessage = error.message || ''
if (errorCode === 'EBUSY' || errorMessage.includes('EBUSY') || errorMessage.includes('locked')) {
window.toast.error(i18n.t('error.backup.file_locked'))
} else if (errorCode === 'ENOENT' || errorMessage.includes('no such file')) {
window.toast.error(i18n.t('error.backup.file_not_found'))
} else if (errorMessage.includes('JSON')) {
window.toast.error(i18n.t('error.backup.file_format'))
} else {
// Show detailed error message for debugging
window.toast.error(i18n.t('error.backup.file_format') + ': ' + errorMessage)
}
}
}
}
@ -314,9 +328,23 @@ export async function restoreFromWebdav(fileName?: string) {
try {
await handleData(JSON.parse(data))
} catch (error) {
} catch (error: any) {
logger.error('[Backup] Error downloading file from WebDAV:', error as Error)
window.toast.error(i18n.t('error.backup.file_format'))
// Distinguish different error types for better user experience
const errorCode = error.code || ''
const errorMessage = error.message || ''
if (errorCode === 'EBUSY' || errorMessage.includes('EBUSY') || errorMessage.includes('locked')) {
window.toast.error(i18n.t('error.backup.file_locked'))
} else if (errorCode === 'ENOENT' || errorMessage.includes('no such file')) {
window.toast.error(i18n.t('error.backup.file_not_found'))
} else if (errorMessage.includes('JSON')) {
window.toast.error(i18n.t('error.backup.file_format'))
} else {
// Show detailed error message for debugging
window.toast.error(i18n.t('error.backup.file_format') + ': ' + errorMessage)
}
}
}
@ -1071,9 +1099,24 @@ export async function restoreFromLocal(fileName: string) {
await handleData(data)
return true
} catch (error) {
} catch (error: any) {
logger.error('[LocalBackup] Restore failed:', error as Error)
window.toast.error(i18n.t('error.backup.file_format'))
// Distinguish different error types for better user experience
const errorCode = error.code || ''
const errorMessage = error.message || ''
if (errorCode === 'EBUSY' || errorMessage.includes('EBUSY') || errorMessage.includes('locked')) {
window.toast.error(i18n.t('error.backup.file_locked'))
} else if (errorCode === 'ENOENT' || errorMessage.includes('no such file')) {
window.toast.error(i18n.t('error.backup.file_not_found'))
} else if (errorMessage.includes('JSON')) {
window.toast.error(i18n.t('error.backup.file_format'))
} else {
// Show detailed error message for debugging
window.toast.error(i18n.t('error.backup.file_format') + ': ' + errorMessage)
}
throw error
}
}