已关闭
[Bug] HarmonyOS 截图失败时错误信息显示 undefined #34
sunkaiyang创建于  9月1日关闭于  9月5日
sunkaiyang
sunkaiyang
9月1日 创建

[Bug] HarmonyOS 截图失败时错误信息显示 undefined

问题描述

在 React Native OpenHarmony 0.77 环境中,使用 react-native-view-shot 截取零尺寸或当前不可截图的 View 时,componentSnapshot.get() 会执行失败流程。

在该场景下,底层 Promise 可能直接 reject 数字错误码 100001,而不是带有 message、code 属性的标准 BusinessError 对象。当前 0.77 实现固定读取 err.message,因此底层错误内容在转换过程中丢失,最终传递到 JavaScript 层的错误信息为:

componentSnapshot failed: undefined

相同 Demo 在 React Native OpenHarmony 0.82 环境中能够正确保留底层错误内容,返回:

componentSnapshot failed: 100001

该问题会导致调用方无法根据错误信息判断截图失败的真实原因,也会降低日志的排障价值。

复现步骤

  1. 使用 React Native OpenHarmony 0.77 环境构建并运行 react-native-view-shot Example 工程。
  2. 打开 ViewShotContinuousTest 测试页面。
  3. 确认页面中的 ViewShot 内容处于显示状态,并能够正常连续截图。
  4. 点击“隐藏内容(可能触发失败)”。
  5. Demo 会将 ViewShot 容器的 width 和 height 设置为 0。
  6. 等待 captureMode="continuous" 再次触发截图。
  7. 查看页面中的截图失败信息或控制台中的 captureFailed 日志。

预期结果

截图失败后,应及时触发 onCaptureFailure 或 Promise rejection,并保留底层返回的实际错误内容。

预期错误信息示例:

componentSnapshot failed: 100001

错误信息中不应出现 undefined。

实际结果

截图进入失败流程,但传递到 JavaScript 层的错误信息为:

componentSnapshot failed: undefined

底层返回的 100001 在读取 err.message 时丢失。

复现概率

必现(100%)。

环境信息

  • React Native Harmony:0.77.22
  • RNOH OpenHarmony HAR:0.77.74
  • @react-native-ohos/react-native-view-shot:3.9.1-beta.1
  • 修复前代码基线:857d6d4
  • 修复分支:77fix
  • 对比环境:
    • React Native Harmony / RNOH OpenHarmony:0.82.30
    • @react-native-ohos/react-native-view-shot:4.0.0-rc.1
  • HarmonyOS/OpenHarmony API 版本:待补充
  • 系统版本:待补充
  • 设备型号:待补充

DEMO(如有)

复现用例:

example/src/Test/ViewShotContinuousTest.tsx

关键代码:

<ViewShot
  ref={myText}
  style={{
    backgroundColor: '#bfa',
    height: isVisible ? 60 : 0,
    width: isVisible ? '100%' : 0,
    overflow: 'hidden',
  }}
  captureMode="continuous"
  onCaptureFailure={getError}
  onCapture={getSuccess}
  options={{ format: 'png' }}
>
  {isVisible && <Text>测试截图</Text>}
</ViewShot>

隐藏 ViewShot:

const toggleVisibility = () => {
  setIsVisible(!isVisible);
};

失败回调:

const getError = (err) => {
  console.log('captureFailed', err.message);
  setErrMsg(err.message);
};

日志/截图对比

版本 / 状态 0.77(修改前) 0.77(修改后)
日志输出 text<br>captureFailed componentSnapshot failed: undefined<br> text<br>captureFailed componentSnapshot failed: 100001<br>
效果截图 0.77 修改前 0.77 修改后

影响范围

受影响的功能和场景包括:

  • captureRef 调用 componentSnapshot.get() 失败的场景。
  • 截取零尺寸、已隐藏、已卸载或当前不可截图的 View。
  • 底层 Promise reject 数字、字符串或其他非标准 BusinessError 数据的场景。
  • 依赖 onCaptureFailure 或 Promise .catch() 获取失败原因的业务。
  • captureScreen 及图片转换、文件保存等需要向 JavaScript 层传递异步错误的路径。

正常截图成功路径、公开接口签名、参数类型和返回类型不受影响。

根因分析

0.77 实现将 Promise rejection 参数声明为 BusinessError,并直接读取:

err.code
err.message

类型声明不会改变运行时收到的数据。当 componentSnapshot.get() 实际 reject 数字 100001 时,该值没有 message 属性,因此下面的错误转换产生了 undefined:

const error = new Error(`componentSnapshot failed: ${err.message}`);

修复方案

参考 0.82 的错误处理方式,增加统一的错误类型和错误信息转换方法:

  • 使用 ViewShotError 统一保存错误信息和错误码。
  • 使用 getErrorMessage() 处理标准 Error 和非标准 rejection 数据。
  • 使用 getErrorCode() 统一获取错误码或回退到 E_UNABLE_TO_SNAPSHOT。
  • 统一 captureRef 和 captureScreen 异步失败路径的错误转换。
  • 不增加截图前零尺寸检查,不改变原有截图成功或失败判定。

对应修复提交:

2c7f018 fix: normalize snapshot errors on HarmonyOS

兼容性说明

  • 不修改公开 API。
  • 不修改方法参数和返回类型。
  • 不修改正常截图成功路径。
  • 原本失败的调用仍然失败,仅将无意义的 undefined 修正为底层实际错误内容。
  • 错误路径存在预期的可观察信息变化,但不构成公共 API Breaking Change。
likedislike
sunkaiyangsunkaiyang
9月1日 关联了pull request:fix: restore ViewShot component flow definitions
cpf-thirdparty-manager
9月2日 评论:

本Issue主要用于开发协作,欢迎在此反馈问题或提出建议

likedislike
sunkaiyangsunkaiyang
9月3日 修改了issue 的描述
sunkaiyangsunkaiyang
9月3日 修改标题为 “[Bug] HarmonyOS 截图失败时错误信息显示 undefined”,原标题为“fix: restore ViewShot component flow definitions”
sunkaiyangsunkaiyang
9月3日 关联了pull request:fix: normalize snapshot errors on HarmonyOS
sunkaiyangsunkaiyang
9月3日 修改了issue 的描述
sunkaiyangsunkaiyang
9月3日 关联了pull request:fix: normalize snapshot errors on HarmonyOS
sunkaiyangsunkaiyang
9月3日 修改了issue 的描述
openharmony_ciopenharmony_ci成员
9月5日 关闭了 issue