diff --git a/apps/web/package.json b/apps/web/package.json
index 0160eff7..e74b9878 100644
--- a/apps/web/package.json
+++ b/apps/web/package.json
@@ -55,6 +55,7 @@
"react": "19.1.0",
"react-blurhash": "0.3.0",
"react-dom": "19.1.0",
+ "react-error-boundary": "6.0.0",
"react-freeze": "1.0.4",
"react-i18next": "15.5.3",
"react-image-gallery": "1.4.0",
diff --git a/apps/web/src/modules/gallery/PhotoMasonryItem.tsx b/apps/web/src/modules/gallery/PhotoMasonryItem.tsx
index dcee8257..e283212d 100644
--- a/apps/web/src/modules/gallery/PhotoMasonryItem.tsx
+++ b/apps/web/src/modules/gallery/PhotoMasonryItem.tsx
@@ -2,6 +2,7 @@ import clsx from 'clsx'
import { m } from 'motion/react'
import { Fragment, useCallback, useEffect, useRef, useState } from 'react'
import { Blurhash } from 'react-blurhash'
+import { ErrorBoundary } from 'react-error-boundary'
import { useTranslation } from 'react-i18next'
import {
@@ -229,15 +230,17 @@ export const PhotoMasonryItem = ({
>
{/* Blurhash 占位符 */}
{data.blurhash && (
-
+ null}>
+
+
)}
{!imageError && (
diff --git a/apps/web/src/pages/(debug)/blurhash.tsx b/apps/web/src/pages/(debug)/blurhash.tsx
index 52a80037..a66751dd 100644
--- a/apps/web/src/pages/(debug)/blurhash.tsx
+++ b/apps/web/src/pages/(debug)/blurhash.tsx
@@ -1,5 +1,6 @@
import { photoLoader } from '@afilmory/data'
import { Blurhash } from 'react-blurhash'
+import { ErrorBoundary } from 'react-error-boundary'
export const Component = () => {
const photos = photoLoader.getPhotos()
@@ -21,16 +22,18 @@ export const Component = () => {
width={photo.width}
className="absolute inset-0"
/>
-
-
-
+ null}>
+
+
+
+
))}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 763d65b6..16166351 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -281,6 +281,9 @@ importers:
react-dom:
specifier: 19.1.0
version: 19.1.0(react@19.1.0)
+ react-error-boundary:
+ specifier: 6.0.0
+ version: 6.0.0(react@19.1.0)
react-freeze:
specifier: 1.0.4
version: 1.0.4(react@19.1.0)
@@ -1960,7 +1963,7 @@ packages:
resolution: {integrity: sha512-fyjAACV62oPV925xFCrH8DR5xWhg9KYtJT4s3u54jxp+L/hbpTY2kIeEFFbFe+a/HCE94zGQMZLIpVTPVZDhaA==}
peerDependencies:
'@types/react': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react: 18.3.1
peerDependenciesMeta:
'@types/react':
optional: true
@@ -6687,6 +6690,11 @@ packages:
peerDependencies:
react: '>=16.13.1'
+ react-error-boundary@6.0.0:
+ resolution: {integrity: sha512-gdlJjD7NWr0IfkPlaREN2d9uUZUlksrfOx7SX62VRerwXbMY6ftGCIZua1VG1aXFNOimhISsTq+Owp725b9SiA==}
+ peerDependencies:
+ react: '>=16.13.1'
+
react-fast-compare@3.2.2:
resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==}
@@ -15457,6 +15465,11 @@ snapshots:
'@babel/runtime': 7.27.6
react: 19.1.0
+ react-error-boundary@6.0.0(react@19.1.0):
+ dependencies:
+ '@babel/runtime': 7.27.6
+ react: 19.1.0
+
react-fast-compare@3.2.2: {}
react-freeze@1.0.4(react@19.1.0):