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

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).

验证步骤

  1. 更新rebar.config中的erlcloud版本并重新编译
  2. 调整receive_message调用代码适配目标版本的API
  3. 确保参数类型(如二进制URL)符合要求
  4. 显式传入Config参数以避免环境配置读取问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 13:44:51