Compare commits

...

1 Commits

Author SHA1 Message Date
kangfenmao
06ce720d6e fix: S3 auto sync ENOENT error with custom-minapps.json
- Add file existence check in FileStorage.readFile to prevent ENOENT errors
- Improve error handling in custom-minapps.json loading across all components
- Add robust JSON parsing and validation for custom minapps
- Handle concurrent access during S3 auto sync operations

Fixes #11255
2025-11-14 14:17:31 +08:00
5 changed files with 82 additions and 9 deletions

View File

@@ -485,6 +485,12 @@ class FileStorage {
): Promise<string> => {
const filePath = path.join(this.storageDir, id)
// 先检查文件是否存在,避免 ENOENT 错误
if (!fs.existsSync(filePath)) {
logger.debug(`File not found: ${filePath}`)
throw new Error(`ENOENT: no such file or directory, open '${id}'`)
}
const fileExtension = path.extname(filePath)
if (documentExts.includes(fileExtension)) {

View File

@@ -87,8 +87,27 @@ const MinApp: FC<Props> = ({ app, onClick, size = 60, isLast }) => {
danger: true,
onClick: async () => {
try {
const content = await window.api.file.read('custom-minapps.json')
const customApps = JSON.parse(content)
let content: string
let customApps: MinAppType[]
try {
content = await window.api.file.read('custom-minapps.json')
customApps = JSON.parse(content)
// 确保解析结果是数组
if (!Array.isArray(customApps)) {
customApps = []
}
} catch (error: any) {
// 如果文件不存在或解析失败,使用空数组
if (error.message?.includes('ENOENT') || error.message?.includes('no such file')) {
customApps = []
} else {
// 其他解析错误,使用空数组
logger.warn('Failed to read custom-minapps.json, using empty array:', error as Error)
customApps = []
}
}
const updatedApps = customApps.filter((customApp: MinAppType) => customApp.id !== app.id)
await window.api.file.writeWithId('custom-minapps.json', JSON.stringify(updatedApps, null, 2))
window.toast.success(t('settings.miniapps.custom.remove_success'))

View File

@@ -67,13 +67,42 @@ const loadCustomMiniApp = async (): Promise<MinAppType[]> => {
let content: string
try {
content = await window.api.file.read('custom-minapps.json')
} catch (error) {
} catch (error: any) {
// 如果文件不存在,创建一个空的 JSON 数组
content = '[]'
await window.api.file.writeWithId('custom-minapps.json', content)
// 检查是否是文件不存在的错误
if (error.message?.includes('ENOENT') || error.message?.includes('no such file')) {
content = '[]'
try {
await window.api.file.writeWithId('custom-minapps.json', content)
} catch (writeError) {
logger.warn('Failed to create custom-minapps.json file:', writeError as Error)
// 如果创建文件失败,仍然返回空数组
}
} else {
// 其他类型的错误,记录并返回空数组
logger.error('Failed to read custom-minapps.json:', error as Error)
return []
}
}
// 确保内容有效
if (!content || content.trim() === '') {
content = '[]'
}
let customApps: any[]
try {
customApps = JSON.parse(content)
// 确保解析结果是数组
if (!Array.isArray(customApps)) {
logger.warn('custom-minapps.json content is not an array, using empty array')
customApps = []
}
} catch (parseError) {
logger.error('Failed to parse custom-minapps.json content:', parseError as Error)
customApps = []
}
const customApps = JSON.parse(content)
const now = new Date().toISOString()
return customApps.map((app: any) => ({

View File

@@ -11,7 +11,8 @@ import type { Topic } from '@renderer/types'
import type { Message } from '@renderer/types/newMessage'
import { classNames } from '@renderer/utils'
import { Popover } from 'antd'
import { ComponentProps, memo, useCallback, useEffect, useMemo, useState } from 'react'
import type { ComponentProps} from 'react';
import { memo, useCallback, useEffect, useMemo, useState } from 'react'
import styled from 'styled-components'
import { useChatMaxWidth } from '../Chat'

View File

@@ -32,8 +32,26 @@ const NewAppButton: FC<Props> = ({ size = 60 }) => {
const handleAddCustomApp = async (values: any) => {
try {
const content = await window.api.file.read('custom-minapps.json')
const customApps = JSON.parse(content)
let content: string
let customApps: MinAppType[]
try {
content = await window.api.file.read('custom-minapps.json')
customApps = JSON.parse(content)
// 确保解析结果是数组
if (!Array.isArray(customApps)) {
customApps = []
}
} catch (error: any) {
// 如果文件不存在或解析失败,使用空数组
if (error.message?.includes('ENOENT') || error.message?.includes('no such file')) {
customApps = []
} else {
// 其他解析错误,使用空数组
logger.warn('Failed to read custom-minapps.json, using empty array:', error as Error)
customApps = []
}
}
// Check for duplicate ID
if (customApps.some((app: MinAppType) => app.id === values.id)) {