Erlang使用erlcloud调用AWS SQS出现function_clause错误求助
问题排查:Erlcloud调用AWS SQS触发function_clause错误
问题背景
用户通过Erlang的erlcloud库访问AWS SQS,相关代码、错误日志及依赖配置如下:
业务代码
-module(server). -export([start/0, loop/1, handle_sqs_request/1]). start() -> application:set_env(erlcloud, aws_access_key_id, os:getenv("AWS_ACCESS_KEY_ID")), application:set_env(erlcloud, aws_secret_access_key, os:getenv("AWS_SECRET_ACCESS_KEY")), application:set_env(erlcloud, aws_region, os:getenv("AWS_REGION")), application:ensure_all_started(erlcloud), spawn(fun() -> loop("queueurl") end). loop(QueueUrl) -> io:format("Fetching messages from queue: ~s~n", [QueueUrl]), handle_sqs_request(QueueUrl), timer:sleep(5000), % Wait for 5 seconds before checking again loop(QueueUrl). handle_sqs_request(QueueUrl) -> io:format("Processing messages from queue: ~s~n", [QueueUrl]), Options = #{max_number_of_messages => 10}, io:format("Options being passed: ~p~n", [Options]), case erlcloud_sqs:receive_message(QueueUrl, Options) of {ok, Messages} -> io:format("Raw messages received: ~p~n", [Messages]), lists:foreach(fun(Msg) -> case maps:get(<<"receipt_handle">>, Msg, undefined) of undefined -> io:format("No receipt handle found in message: ~p~n", [Msg]); ReceiptHandle -> io:format("Deleting message with receipt handle: ~s~n", [ReceiptHandle]), erlcloud_sqs:delete_message(QueueUrl, ReceiptHandle) end end, Messages), ok; {error, Reason} -> io:format("Error receiving messages: ~p~n", [Reason]) end.
错误日志
1> server:start(). Fetching messages from queue: queurl <0.226.0> Processing messages from queue: queuurl Options being passed: #{max_number_of_messages => 10} =ERROR REPORT==== 11-Dec-2024::17:07:24.378596 === Error in process <0.226.0> with exit value: {function_clause, [{erlcloud_sqs,receive_message, ["queurul", #{max_number_of_messages => 10}, 1,none,none, [all],
依赖配置(rebar.config)
{erl_opts, [debug_info]}. {deps, [ {erlcloud, {git, "https://github.com/erlcloud/erlcloud.git", {branch, "master"}}} ]}. {shell, [ {apps, [appname]} ]}.
用户已确认:AWS凭证加载正常、权限满足要求、队列URL有效、本地CLI可正常操作SQS,但代码调用始终报错,调整语法和更换erlcloud版本未解决问题。
错误根因
function_clause错误表明调用erlcloud_sqs:receive_message时的参数组合与该函数的所有定义签名均不匹配。当前erlcloud master分支的receive_message函数已变更API,不再支持(QueueUrl, OptionsMap)的调用方式,而是需要传入离散参数或配合配置对象。
从错误日志的参数列表可以看出,系统尝试将你的调用适配为多参数签名,但参数类型/数量不匹配,触发函数子句不匹配错误。
解决方案
1. 切换到erlcloud稳定版本
master分支属于开发分支,API可能不稳定。修改rebar.config指定稳定发布版本(如3.0.0):
{deps, [ {erlcloud, "3.0.0"} ]}.
执行rebar3 get-deps && rebar3 compile更新依赖后重试。
2. 适配最新API调用方式
如果坚持使用master分支,需按照当前erlcloud_sqs.erl的函数签名调用。例如,显式传入必要参数和配置对象:
handle_sqs_request(QueueUrl) -> io:format("Processing messages from queue: ~s~n", [QueueUrl]), Config = erlcloud_aws:default_config(), % 获取默认配置(加载环境变量的凭证) % 调用receive_message的完整签名:QueueUrl, MaxMsgCount, VisibilityTimeout, WaitTime, AttrNames, MsgAttrNames, Config case erlcloud_sqs:receive_message(QueueUrl, 10, undefined, undefined, [all], [all], Config) of {ok, #{messages := Messages}} -> % 注意新版本返回的是包含messages键的map io:format("Raw messages received: ~p~n", [Messages]), lists:foreach(fun(#{<<"receipt_handle">> := ReceiptHandle}) -> io:format("Deleting message with receipt handle: ~s~n", [ReceiptHandle]), erlcloud_sqs:delete_message(QueueUrl, ReceiptHandle, Config) end, Messages), ok; {ok, _EmptyResult} -> io:format("No messages received~n"), ok; {error, Reason} -> io:format("Error receiving messages: ~p~n", [Reason]) end.
3. 统一参数类型
确保队列URL为二进制类型(部分erlcloud版本要求),修改start/0中的队列URL传递:
spawn(fun() -> loop(list_to_binary("queueurl")) end).
验证步骤
- 更新rebar.config中的erlcloud版本并重新编译
- 调整
receive_message调用代码适配目标版本的API - 确保参数类型(如二进制URL)符合要求
- 显式传入Config参数以避免环境配置读取问题
内容的提问来源于stack exchange,提问作者soy3
相关产品推荐
相关产品推荐

