You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

生产环境sorbet-runtime中T.cast偶发NoMethodError问题咨询

生产环境sorbet-runtime T.cast瞬态NoMethodError问题排查与咨询

问题背景

我们在生产服务的T.cast调用链路中遇到了瞬态NoMethodError报错,相关已知信息整理如下:

  • 问题出现于0.5.10012版本的sorbet-runtime中
  • 故障每次仅影响单台主机,通常呈短时间爆发特征(例如报错持续时长小于10分钟后自行消失)
  • 部分生产服务每日都会出现该报错,其余服务约每周出现一次
  • 该问题是在我们将sorbet-runtime从0.5.6001版本升级至0.5.9976版本(跨度2年的版本变更)后才出现的;此前我们一直锁定旧版本,直到完成对已废弃的--dsl-plugins特性的迁移才执行升级
  • 当前使用的Ruby版本为2.7.4
  • 我们已在生产环境禁用运行时校验,配置为:T::Configuration.default_checked_level = :never

初步排查结论

短时间内T::Utils.coerce(type)会返回不符合预期的值(并非T::Types::Base的子类),导致在执行error_message_for_obj校验时抛出错误。

采集到的报错栈

NoMethodError: undefined method `valid?' for {:mode=>:compat}:Hash
  from sorbet-runtime (0.5.10012) lib/types/types/intersection.rb:33:in `block in valid?'
  from sorbet-runtime (0.5.10012) lib/types/types/intersection.rb:33:in `all?'
  from sorbet-runtime (0.5.10012) lib/types/types/intersection.rb:33:in `valid?'
  from sorbet-runtime (0.5.10012) lib/types/types/base.rb:133:in `error_message_for_obj'
  from sorbet-runtime (0.5.10012) lib/types/private/casts.rb:8:in `cast'
  from sorbet-runtime (0.5.10012) lib/types/_types.rb:133:in `cast'
  from < our code>

触发报错的业务代码行

T.cast(self, T.all(T::Props::Serializable, Object)).as_json

临时调试方案

目前尚未找到本地复现该问题的方法,因此针对性为T.cast添加了调试用猴子补丁,用于捕获错误、打印更多上下文日志,且不再抛出错误直接返回原值,补丁代码如下:

# frozen_string_literal: true

module SorbetMonkeyPatches
  module TcastDebug
    module ClassMethods
      def cast(value, type, checked: true)
        super
      rescue NoMethodError => e
        Rails.logger.error(
          message: "[sorbet] - #{value.try(:class)} to #{type.try(:class)}",
          src_value: value.inspect,
          src_type: type.inspect,
          coerce_res: T::Utils.coerce(type).inspect,
        )
        value # ultimately don't want assertions from T.cast...this should return the same value unchanged
      end
    end
  end
end

if ENV["SORBET_DEBUG_UPGRADE"] == "true"
  ::T.singleton_class.prepend(SorbetMonkeyPatches::TcastDebug::ClassMethods)
end

异常日志样例

开启调试补丁后,采集到的异常日志样例如下:

[sorbet] - Class to Module {"src_value":"ProductsDomain::Api::LocaleCode","src_type":"T::Props::CustomType","coerce_res":"\"ssl_min_protocol_version\""}

...
[sorbet] - Class to Module {"src_value":"ProductsDomain::Api::LocaleCode","src_type":"T::Props::CustomType","coerce_res":"[\"workflow_state\", \"active\"]"}

正常情况下coerce_res应当返回T::Types::Base的子类实例,而非上述随机字符串。我们初步推测是类型强制转换缓存被意外污染,从而导致该问题。

咨询问题

  • 该问题是否有过已知的上报案例?
  • 对于问题修复或后续排查方向,有无相关建议?
  • 我们期望在禁用运行时校验时,T.cast不会抛出任何错误,是否需要重写T.cast方法定义中的可选checked参数?

感谢您的协助,若需要更多调试信息可随时告知。

内容的提问来源于stack exchange,提问作者Osman Khwaja

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 21:24:31