新Nerves项目执行iex -S mix出现FunctionClauseError报错求助
FunctionClauseError在handle_info/2的问题 我之前帮人排查过不少类似的版本兼容问题,结合你的环境(Elixir 1.6.0 + OTP 20)来看,这个错误的核心原因是你安装的Nerves版本和当前Elixir/OTP版本不匹配,导致Nerves.Runtime.Kernel.UEvent.handle_info/2函数的参数 clause 和运行时传入的消息不匹配——哪怕你在文件里能看到这个函数定义,但传入的消息格式不符合任何已定义的 clause,就会触发这个错误。
下面是具体的排查和解决步骤:
第一步:确认Nerves版本兼容性
Nerves的新版本已经不再支持Elixir 1.6和OTP 20了,你需要安装和你的环境兼容的旧版本Nerves。比如Nerves v1.7.x系列是最后一批支持OTP 20的版本,先查看当前安装的Nerves版本:mix nerves.info如果显示的版本高于1.7,那肯定是不兼容的。
第二步:重装兼容版本的Nerves Bootstrap
先卸载当前的Nerves Bootstrap:mix archive.uninstall nerves_bootstrap然后安装兼容的版本(比如1.7.0):
mix archive.install hex nerves_bootstrap 1.7.0第三步:重新创建项目并锁定依赖版本
重新创建MIX_TARGET=rpi3的项目,然后打开mix.exs,确保Nerves相关依赖的版本锁定在兼容范围内:defp deps do [ {:nerves, "~> 1.7", runtime: false}, {:nerves_runtime, "~> 0.11"}, # 其他依赖保持和项目匹配 ] end运行
mix deps.get拉取正确版本的依赖。第四步:清理缓存并重新编译
旧的编译缓存可能残留不兼容的代码,执行以下命令彻底清理后重新编译:mix clean && mix deps.clean --all && mix deps.get && mix compile之后再运行
iex -S mix应该就能正常启动了。
补充说明下为什么明明能看到函数定义还是报错:函数的handle_info/2可能定义了多个 clause(比如匹配不同类型的消息),但运行时传入的消息格式和所有已定义的 clause 都不匹配,Erlang VM就会抛出FunctionClauseError——这不是函数不存在,而是没有匹配的参数组合。这种情况在依赖版本和运行环境不兼容时非常常见,因为不同版本的Nerves可能对UEvent消息的结构做了调整。
内容的提问来源于stack exchange,提问作者Yugandhar Chaudhari

