JSError 常见错误处理

开发者 JSError 问题排查流程

小程序执行环境的限制

与传统的网页开发不同,小程序的执行环境一定程度上限制了开发者对代码运行时信息的把握。

开发者工具的执行环境只是对真机环境的模拟,目前还不能做到完全代表真机表现,因此在开发测试阶段开发者很难做到让测试用例完全覆盖所有场景和某些小概率时序问题。

再优秀的开发者也无法保证线上的代码完全不出错,重要的是,当错误真正发生的时候,开发者能够获取到足够的信息,定位问题、分析问题、解决问题,从而提升小程序代码的稳定性。

与开发者工具和真机调试工具不同,运维中心内的 JSError 数据代表着绝对真实的线上小程序质量,是唯一能够准确衡量业务代码的稳定性的指标。

如何查看并分析 JSError

错误信息是从哪里收集来的?
小程序底层框架捕获到错误对象后,会将原始错误堆栈和经过框架包装后的错误 message 上报到开发者运维平台,帮助开发者定位和排查问题。

错误对象的组成:Error = message + stack

能够协助错误分析的其他信息:错误发生时间点、错误量级,影响用户数,swan 版本。

JSError 常见错误处理 - 图1

错误堆栈:是能够定位问题的最直观的信息。

原始的错误堆栈中包含着代码崩溃时的函数调用栈信息,利用这些线上代码的调用信息,结合小程序代码编译时产出的 sourcemap,开发者就可以精准的还原出代码结构,并定位到发生错误的那一行代码,让线上问题的排查变得像本地开发调试时一样简单。

对于能够明确为开发者业务代码运行时引起的问题,开发者可点击 JSError 右侧的详情按钮,查看错误详细堆栈并定位错误发生位置的源码,此类问题开发者可以直接定位到小程序源码中发生错误的那一行代码,结合错误 message 和实际业务代码中可能存在的问题对错误日志进行分析。

举个例子,[setPageInfo Error] Recommended to call setPageInfo in Page.onShow
此类问题发生在过早的调用 setPageInfo 这个 API 时,由于拿不到当前页面的足够信息,框架底层会在此时抛出一个错误,来提示开发者正确的使用方式。

JSError 常见错误处理 - 图2

对于一些可能没有错误堆栈的 JSError 日志,开发者能够利用的信息就只有错误发生时间、错误版本分布、错误具体量级等趋势数据。
此时开发者虽然不能直接找到问题原因所在,但通过 JSError 日志的变化趋势,可以推测到是哪一次版本迭代引入了新的错误,或是让某个类型的错误出现了突增。
开发者可以根据受影响的用户面积,进一步排查版本迭代中的代码 diff,采取修复或是回滚等补救措施。

举个例子,从图中的 JSError 变化趋势和版本分布来看,在 12.03 当天错误量有比较明显的增长,且可以观察到,错误集中在小程序的 2.1.27.1 版本中,那么就意味着很有可能是 12.03 当天发布的小程序版本 2.1.27.1 ,在线上存在很大的问题,可能会对业务产生影响,此时应尽快排查和定位问题,及时止损。

JSError 常见错误处理 - 图3

如何区分是业务问题 or 小程序框架问题

为什么会存在一些看不懂的错误?
由于小程序底层框架运行时和开发者代码逻辑依赖较为复杂,目前还不能做到百分百准确的区分错误是由开发者的代码执行引起的,还是触发了小程序框架运行时的某些异常导致的。

区分错误的核心依据还是原始错误堆栈,能够通过 JSError 面板中的错误详情,一键还原的错误,都一定为开发者业务代码引入的问题。

但反过来,错误堆栈显示错误来源于小程序底层框架的问题,就一定不需要开发者关心吗?并不一定。

为了保证小程序的正常稳定运行, 小程序底层框架对开发者的很多操作都做了制约。

而如果开发者的业务代码在运行过程中,存在某些地方不符合框架约定和语法的逻辑,比如错误的使用一个 API、在某些拿不到元素节点的生命周期执行一些依赖视图的操作,或是缺少相关的配置项,这些都有可能触发框架内部抛出异常,并中断后续逻辑,从而影响到小程序的稳定性和用户实际体验。

对于这些非业务代码异常直接引起的错误,框架会尽可能的将最后的错误信息上报给开发者,供开发者分析和排查业务代码中存在的问题。

而对于某些框架引入的 bug,或是开发者排查后认为该条 JSError 与自己实际业务代码不相关,怀疑为误报的 case,运维中心也会提供反馈入口,为开发者提供技术支持的通路。

业务方 JSError 场景异常速查字典
不能被框架生命周期或内部方法捕获到的错误,目前上报的 message 仍为原始格式。
例如TypeError: Cannot read property 'show' of undefined

这里列出了目前典型的业务代码引起的 JSError 的错误信息格式和常见的原因。
一条完整的 JSError 错误 message 一般由前缀信息 + 原生错误 message 组成,例如:
JSError 常见错误处理 - 图4

错误前缀信息常见场景 & 原因错误级别备注
[Lifecycle Fail] call App.onLaunch method fail:生命周期存在未捕获错误,涵盖小程序所有 App 级别,Page 级别,Component 级别生命周期。【Error严重】任何没有捕获到的错误都会中断该生命周期后续逻辑执行最常见的开发者错误,意味着业务代码在生命周期执行阶段报错
[Component Error] Call component method fail:Component 中自定义方法执行失败【Error 严重】 会导致后续逻辑中断-
[Component Error] Can’t find components/bar, please check your config自定义组件配置有误【Error 严重】 会影响组件初始化
[Page Error] Call current page foo method fail:Page 中自定义方法执行失败【Error 严重】 会导致后续逻辑中断-
[Open new Page fail] from pages/index to pages/feed页面跳转相关能力调用失败,涵盖所有路由能力:navigateTo / redirectTo / switchTab / relaunch【Error 严重】页面跳转失败,用户的操作没有得到预期的结果最常见的原因为跳转路径未配置,页面参数拼接错误,跳转 url 不合法等
[Skeleton Error] Skeleton template path error.骨架屏路径配置错误【Warning 警告】 会导致骨架屏加载异常-
[setPageInfo Error] Recommended to call setPageInfo in Page.onShow过早的调用 setPageInfo【Warning 警告】 会导致 setPageInfo 失败过早的调用 setPageInfo 会获取不到页面相关信息
[Plugin Error] get plugin compile path error:插件编译错误,没有在 .json 文件中找到对应插件配置信息【Warning 警告】插件加载异常-
[Dynamic(swan-interaction)][Developer error] error commentParam: {}一站式互动组件动态库错误【Warning 警告】互动组件 commentParam 内部参数为必填字段。不建议存在留空的情况

如果为小程序框架侧问题,该如何反馈?

我们将在运维中心面板增加误报反馈入口,开发者可一键上报,小程序官方有专门的工作人员对接处理。

应用 JSError 的小程序案例

以下为 JSError 帮助到的小程序(排名不分先后)。

小程序导致的问题影响
本地宝小程序逻辑层卡死功能异常
百度知道视频流统计问题,导致统计策略完全失效功能异常
百度百科大范围白屏,原因是 npm 镜像服务挂掉问题白屏
孔夫子旧书网逻辑错误白屏
康波财经分包与自定义路由逻辑问题,到达率下降 15%白屏
时间财富路由地址不存在,pageNotFound 中死循环跳转失效
台风路径查询旧包逻辑兼容问题,导致小范围白屏白屏
企查查路由地址不存在跳转失效
安居客路由地址不存在跳转失效
汽车之家极速版逻辑错误,导致部分页面白屏白屏
蜜小助恋爱聊天话术setPageInfo 图片设置失效,影响爬虫功能异常
爱奇艺内部逻辑错误,导致部分功能异常功能异常
某小程序使用插件不合法白屏
赢众海外咨询逻辑死循环,导致功能异常白屏
58 白菜二手车页面逻辑问题功能异常
大众点评逻辑错误跳转失效
携程逻辑死循环,导致一直显示 Toast功能异常
喵时尚资讯网络资源问题,首页和二级页部分图片不显示功能异常
圆通快递助手内部逻辑异常跳转失效

常见问题

Q:如何上传 sourcemap 呢?

A:当在开发者工具发布小程序时,sourcemap 为默认勾选上传。

Q:有些 error 信息看不懂?

A:可能是小程序框架的错误,请及时反馈。

Q:如何根据错误堆栈查看源码?

A:当开发者提供 sourcemap 后,可点击错误 message 右侧的详情按钮,打开源码页面查看。

Q:为什么有时候还原不出源码?

A:官方只保存最近一份 sourcemap,其它版本的错误堆栈不能进行还原。

Q:没有数据显示是什么情况?

A:数据延迟 2 小时,只展示当前线上包的数据,刚发布新的包版本后存在短期内无数据的情况。

Q:异常解决方案有哪些?

A:简单的 error 直接进行查看后修复;复杂的 error 可点击 error message 右侧详情,根据错误堆栈查看具体发生错误的原代码。