资讯动态

Appium base-driver 的 MJSONWP 错误体系:错误码、异常类与辅助方法全解

发布时间:2026/9/13 3:34:33 来源:尧图企业网站定制
Appium base-driver 的 MJSONWP 错误体系错误码、异常类与辅助方法全解【免费下载链接】appiumCross-platform automation framework for all kinds of apps, built on top of the W3C WebDriver protocol项目地址: https://gitcode.com/GitHub_Trending/ap/appium在 Appium 的服务端实现中每一次 WebDriver 命令失败最终都会被翻译成带数字状态码和 W3C 错误签名的 HTTP 响应。本文基于packages/base-driver/docs/mjsonwp/errors.md文档及其对应源码完整梳理appium/base-driver包导出的 MJSONWPMobile JSON Wire Protocol错误类家族包括每个错误码、类名与默认消息的对照表、isErrorType/errorFromCode两个辅助方法的用法以及这些错误类在协议层如何被转换为实际的 W3C HTTP 错误响应。读完本文你可以在编写驱动driver或插件时正确地抛出、识别和转换协议错误并在调试失败请求时快速定位到对应的错误码语义。MJSONWP 错误体系定位MJSONWP 是在经典 JSON Wire Protocol 之上、为移动端扩展了上下文context等概念的一套错误/协议约定。文档指出本包导出的错误类覆盖两类来源Selenium 规范中的每种错误类型对应 JsonWireProtocol 的 Response Status Codes以及移动规范中定义的两类上下文错误——NoSuchContextError码 35与InvalidContextError码 36。这些错误类都通过模块导出的errors对象访问构造时接受一个字符串消息参数若不传消息则使用各错误内置的默认 Details 文案。所有错误类的统一实现在 errors.ts 中包入口 index.ts 通过export * from ./protocol将其全部透出。文档示例中的import { errors, errorFromCode } from appium-base-driver使用的是旧包名当前 monorepo 中的实际包名是appium/base-driver见 package.json导出名保持不变见下文辅助方法一节。错误码与错误类对照表以下表格完整继承自官方文档并基于 errors.ts 中每个类实现的code()/error()/w3cStatus()静态方法补充了该错误在 W3C 模式下的 HTTP 状态码与 W3C 错误签名CodeClass NameDetailsW3C HTTP 状态码W3C error 签名MJSONWPError1Base class for other errors基础类——6NoSuchDriverErrorA session is either terminated or not started会话已终止或未创建404invalid session id7NoSuchElementErrorAn element could not be located on the page using the given search parameters元素未找到404no such element8NoSuchFrameErrorA request to switch to a frame could not be satisfied because the frame could not be found404no such frame9UnknownCommandErrorThe requested resource could not be found, or a request was received using an HTTP method that is not supported by the mapped resource404unknown command10StaleElementReferenceErrorAn element command failed because the referenced element is no longer attached to the DOM404stale element reference11ElementNotVisibleErrorAn element command could not be completed because the element is not visible on the page400element not visible12InvalidElementStateErrorAn element command could not be completed because the element is in an invalid state (e.g., attempting to click a disabled element)400invalid element state13UnknownErrorAn unknown server-side error occurred while processing the command500unknown error405NotYetImplementedErrorThe operation requested is not yet implemented by the driver405unknown method405NotImplementedErrorThe operation requested will not be implemented by the driver405unknown method15ElementIsNotSelectableErrorAn attempt was made to select an element that cannot be selected400element not selectable17JavaScriptErrorAn error occurred while executing user supplied JavaScript500javascript error19XPathLookupErrorAn error occurred while searching for an element by XPath400invalid selector21TimeoutErrorAn operation did not complete before its timeout expired408timeout23NoSuchWindowErrorA request to switch to a different window could not be satisfied because the window could not be found404no such window24InvalidCookieDomainErrorAn illegal attempt was made to set a cookie under a different domain than the current page400invalid cookie domain25UnableToSetCookieErrorA request to set a cookies value could not be satisfied500unable to set cookie26UnexpectedAlertOpenErrorA modal dialog was open, blocking this operation500unexpected alert open27NoAlertOpenErrorAn attempt was made to operate on a modal dialog when one was not open404no such alert28ScriptTimeoutErrorA script did not complete before its timeout expired408script timeout29InvalidElementCoordinatesErrorThe coordinates provided to an interactions operation are invalid400invalid coordinates30IMENotAvailableErrorInput Method Editor was not available500unsupported operation31IMEEngineActivationFailedErrorAn Input Method Editor engine could not be started500unsupported operation32InvalidSelectorErrorArgument was an invalid selector (e.g., XPath/CSS)400invalid selector33SessionNotCreatedErrorA new session could not be created500session not created34MoveTargetOutOfBoundsErrorTarget provided for a move action is out of bounds500move target out of bounds35NoSuchContextErrorContext provided (e.g.,WEBVIEW_42) does not exist500unknown error36InvalidContextErrorThe operation could not be performed in the current context500unknown errorBadParametersError2The parameters specified for the operation are incorrect400invalid argument1文档中的MJSONWPError是所有 Selenium 规范错误的基类BadParametersError除外本身不属于该规范。在当前源码中该基类由ProtocolError承载继承自BaseError此外源码中还有一个同名的MJSONWPError接口用于描述 JSONWP 风格的错误响应体{status, value}见 errors.ts两者是历史命名演化的产物。2BadParametersError不属于 Selenium 规范专门处理请求参数管理它是InvalidArgumentErrorW3Cinvalid argument的子类见 errors.ts。值得注意的是两条 405 错误NotYetImplementedError与NotImplementedError在当前源码中都是UnknownMethodError的别名子类仅默认消息不同Method has not yet been implemented / Method is not implemented实现见 errors.ts。源码层面的扩充文档未列出的错误类errors对象errors.ts实际导出的类比文档表格更多其中一部分是 W3C WebDriver 规范新增、没有历史 JSONWP 状态码的错误。编写现代驱动时同样可能用到CodeClass NameW3C HTTP 状态码W3C error 签名说明60ElementNotInteractableError400element not interactable元素不可指针/键盘交互61InvalidArgumentError400invalid argument命令参数无效或格式错误62NoSuchCookieError404no such cookie未找到匹配的 cookie63UnableToCaptureScreen500unable to capture screen截图失败64ElementClickInterceptedError400element click intercepted点击被其他元素遮挡拦截65NoSuchShadowRootError404no such shadow root元素没有关联 shadow root源码注释说明此前曾被误判为UnknownError—InsecureCertificateError400insecure certificate导航命中证书告警405UnknownMethodError/UnsupportedOperationError405 / 500unknown method/unsupported operation方法不匹配 / 服务端不支持该命令—ProxyRequestError——代理下游请求失败时抛出需用getActualError()取出真正的协议错误此外源码中还提供了两个零成本别名NoSuchAlertError等价于NoAlertOpenErrorInvalidCoordinatesError等价于InvalidElementCoordinatesError见 errors.ts 与 errors.ts。类层次结构ProtocolError 如何携带双协议信息从源码结构看整个错误体系是一个清晰的继承树BaseError extends Error处理cause链接与堆栈拼接。若构造时传入cause其堆栈会以 The above error is caused by 为分隔合并进stack见 errors.ts。这保证了即使驱动内部错误被多层包装原始堆栈信息也不会丢失。ProtocolError extends BaseError每个具体错误类的真正基类持有三个关键字段见 errors.tsjsonwpCodeJSONWP/MJSONWP 数字状态码即上表 Code 列errorW3C 错误签名字符串如no such elementw3cStatusW3C 模式下的 HTTP 状态码取自http-status-codes包的StatusCodes。另有一个可设置的stacktrace访问器用于在从 W3C 响应体还原错误时保存下游传来的堆栈。每个具体错误类都用static code()/static w3cStatus()/static error()三个静态方法声明自己的三要素构造函数的第一个参数msg缺省时回落到默认 Details 文案第二个参数cause用于保留原始异常。例如NoSuchElementError的实现errors.tsexport class NoSuchElementError extends ProtocolError { constructor(message: string , cause?: Error) { super( message || An element could not be located on the page using the given search parameters., NoSuchElementError.code(), // 7 NoSuchElementError.w3cStatus(), // 404 NoSuchElementError.error(), // no such element cause, ); } static code() { return 7; } static w3cStatus() { return HTTPStatusCodes.NOT_FOUND; } static error() { return no such element; } }ProtocolError还提供了bidiErrObject(id)方法用于生成 WebDriver BiDi 协议的错误响应对象{id, type: error, error, stacktrace, message}errors.ts说明同一套错误类同时服务于 W3C 同步协议、JSONWP 与 BiDi 三种响应形态。辅助方法isErrorType 与 errorFromCode文档定义的errors对象之外还有两个核心辅助方法。isErrorType (err, type)判断一个错误对象是否属于某一类 MJSONWP 错误。其实现非常直接——比较构造器名称errors.tsexport function isErrorTypeT(err: any, type: ClassT): err is T { return err.constructor?.name type.name; }由于按构造器名匹配别名类如NoSuchAlertError也能正确识别为自身类型。典型用法继承自文档示例包名更新为当前值import { errors, isErrorType } from appium/base-driver; try { // do some stuff... } catch (err) { if (isErrorType(err, errors.InvalidCookieDomainError)) { // process... } }errorFromCode (code, message)根据 MJSONWP 数字状态码取回对应错误类的实例。包入口将其作为errorFromMJSONWPStatusCode的别名导出见 index.ts后者是真实实现在 errors.ts 中通过启动时构建的jsonwpErrorCodeMap错误码 → 类 的映射查表未命中的码会降级为UnknownErrorvalue参数既可以是字符串也可以是带message属性的对象函数会自动取出消息字段。import { errors, errorFromCode } from appium/base-driver; let error errorFromCode(6, an error has occurred); console.log(error instanceof errors.NoSuchDriverError); // true console.log(error.message an error has occurred); // true与之对称的还有errorFromW3CJsonCode(signature, message, stacktrace)errors.ts按 W3C 错误签名字符串如no such element查w3cErrorCodeMap并可附带 stacktrace。两者分别对应从 JSONWP 状态码还原与从 W3C 签名还原两个方向是代理层解析下游响应的关键。从异常到 HTTP 响应getResponseForW3CError错误类最终如何变成客户端收到的响应入口函数是getResponseForW3CErrorerrors.ts它把任意错误翻译为[httpStatus, {value: {error, message, stacktrace}}]形式的 W3C 响应转换策略分三级若错误对象同时拥有error和w3cStatus属性即ProtocolError实例直接取其字段构造响应若是ProxyRequestError拥有getActualError方法先调用它还原出真正的协议错误再转换。getActualError()的逻辑是响应体带status字段则按 MJSONWP 状态码还原errorFromMJSONWPStatusCode带 W3C 风格value.error则按签名还原errorFromW3CJsonCode否则包成UnknownErrorerrors.ts其它任何未知错误一律包装为UnknownError500,unknown error。这条链路在仓库内有多处真实调用点可以印证其核心地位协议路由层protocol.ts 在命令执行 catch 分支中调用getResponseForW3CError(actualErr)生成最终 HTTP 状态码与响应体Express 中间件middleware.ts 的全局错误处理器与 middleware.ts 的 404 处理器UnknownCommandError都走同一函数代理层proxy.ts 在转发下游请求失败时用isErrorType(err, errors.ProxyRequestError)判断是否需要getActualError()随后交给getResponseForW3CError统一格式化。BadParametersError是一个值得细看的特殊错误它不接收任意消息而是接收paramReqs{required, optional?}与实际收到的参数名列表由generateBadParametersMessage生成结构化的诊断消息——依次列出缺失的必填参数、已知的必填参数、可选参数与用户实际提供的参数errors.ts。因此当客户端收到 400invalid argument时消息本身就能告诉你缺了哪个参数。状态码速查表statusCodes 与 getSummaryByCode除了异常类appium/base-driver还导出一份纯数据形态的状态码表文档目录中 jsonwp-status 模块经 index.ts 以statusCodes/getSummaryByCode之名导出import {statusCodes, getSummaryByCode} from appium/base-driver; getSummaryByCode(0); // The command executed successfully. getSummaryByCode(7); // An element could not be located on the page using the given search parameters. getSummaryByCode(1000); // An error occurred未知码的回退文案statusCodes覆盖了码 0Success到 35 的全部 JSONWP 状态码及人类可读 summarygetSummaryByCode接受数字或字符串内部parseInt查不到时返回An error occurred。其单测见 status.spec.ts。该表也被代理层实际使用当下游返回非 0 状态码而消息为空时proxy.ts 会用getSummaryByCode(status)兜底生成消息再交给errorFromMJSONWPStatusCode构造错误。测试印证与使用建议错误体系的正确性由单测逐条固化errors.spec.ts 以errorsList数组逐一断言每个错误类的名称、默认消息、W3C 签名与状态码并专门覆盖getResponseForW3CError的典型场景——普通Error应得 500unknown error且堆栈含 caused by、NoSuchElementError404no such element、BadParametersError400invalid argument且消息含缺失参数等均可作为行为契约的权威参照。对驱动/插件开发者的实战建议抛错时选择精确的错误类而不是笼统抛Error只有ProtocolError子类才能映射到正确的 HTTP 状态码与 W3C 签名未识别的错误一律退化为 500unknown error会让客户端无法做针对性重试或断言。用cause保留原始异常BaseError会自动合并 cause 堆栈方便排查元素未找到这类表象错误背后的真实故障。参数校验失败统一用BadParametersError让自动生成消息代替手写拼接客户端可据此定位缺参。判断错误类型用isErrorType跨协议还原错误用errorFromCode/errorFromW3CJsonCode代理下游失败用ProxyRequestError.getActualError()取真实错误。参考文档目录中另一篇 protocol-methods.md 可对照每个协议端点理解哪些命令失败时通常会抛出哪些错误例如超时端点未实现时对应的TimeoutError。小结packages/base-driver/docs/mjsonwp/errors.md描述的 MJSONWP 错误体系在appium/base-driver源码中落实为一张 3 个维度JSONWP 码 / W3C 签名 / HTTP 状态码齐备的异常类表加上isErrorType类型判断、errorFromCode码表还原与getResponseForW3CError响应转换三条主链路。理解这套体系后你不仅能读懂 Appium 失败响应中每个状态码的确切含义也能在自建驱动或插件时以协议兼容的方式抛错、捕获与翻译错误让客户端库的异常类型与重试逻辑正常工作。【免费下载链接】appiumCross-platform automation framework for all kinds of apps, built on top of the W3C WebDriver protocol项目地址: https://gitcode.com/GitHub_Trending/ap/appium创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价