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

AWS Step Functions自定义状态出现不可达状态与Schema验证失败问题排查

问题分析与解决:AWS Step Functions自定义Map状态部署报错

报错信息

Resource handler returned message: "Invalid State Machine Definition: 'SCHEMA_VALIDATION_FAILED: Expected value of type [ARRAY] at /States/ProcessFile/Catch, MISSING_TRANSITION_TARGET: State "TerminalState" is not reachable. at /States/ProcessFile/ItemProcessor/States/TerminalState' (Service: AWSStepFunctions; Status Code: 400; Error Code: InvalidDefinition; Request ID: cdbda38e-12d5-4dee-81a3-020a2a00cd32; Proxy: null)" (RequestToken: 81bdef9c-408a-d6b2-af56-e1f42eb54c50, HandlerErrorCode: InvalidRequest)

用户代码(自定义Map状态)

IDictionary<string, object> stateJson = new Dictionary<string, object> {
                { "Type", "Map" },
                { "ItemProcessor", new Dictionary<string, object> {
                    { "ProcessorConfig", new Dictionary<string, object> {
                        { "Mode", "DISTRIBUTED" },
                        { "ExecutionType", "EXPRESS" }
                    } },
                    { "StartAt", "AudienceListUserValidation" },
                    { "States", new Dictionary<string, object> {
                        { "AudienceListUserValidation", new Dictionary<string, object> 
                            {
                                { "Type", "Task" },
                                { "Resource", "arn:aws:states:::lambda:invoke" },
                                { "Parameters", new Dictionary<string, object> {
                                    { "FunctionName", userValidationfunction.Function.FunctionName },
                                    { "Payload.$", "$" }
                                } },
                                { "ResultPath",  JsonPath.DISCARD },
                                { "Catch", catchSerialized },
                                { "End", true },
                            } 
                        },
                        { "TerminalState", new Dictionary<string, object>
                            {
                                { "Type", "Task"},
                                { "Resource", "arn:aws:states:::lambda:invoke"},
                                { "Parameters", new Dictionary<string, object>
                                    {
                                        { "FunctionName", errorFunction.Function.FunctionName },
                                        { "Payload.$", "$" }
                                    }
                                },
                                { "End", true }
                            }
                        }
                    } }
                } },
                { "Label", "ProcessFile" },
                { "MaxConcurrency", 5 },
                { "ItemReader", new Dictionary<string, object> 
                    {
                        { "Resource", "arn:aws:states:::s3:getObject" },
                        { "ReaderConfig", new Dictionary<string, object> 
                            {
                                { "InputType", "CSV" },
                                { "CSVHeaderLocation", "FIRST_ROW" }
                            } 
                        },
                        { "Parameters", new Dictionary<string, object> 
                            {
                                { "Bucket.$", "$.S3BucketName" },
                                { "Key.$", "$.S3FileName" }
                            } 
                        }
                    } 
                },
                { "ItemSelector", new Dictionary<string, object>
                    {
                        { "MatchingFieldId.$", "$$.Map.Item.Value.Email"},
                        { "FileUploadId.$", "$.FileUploadId"}
                    }
                },
                { "ResultPath",  JsonPath.DISCARD } 
            };

catchSerialized定义

var catchSerialized = JsonConvert.SerializeObject(new[] { 
                new { 
                    ErrorEquals = new[] { "States.ALL" }, 
                    Next = "TerminalState" 
                } 
            });

用户疑问

原本期望AudienceListUserValidation执行失败时跳转至TerminalState,但出现上述报错。另外使用CDK,是否可以用OnFailure属性替代Catch?示例代码:

audienceListUserValidationFuncProps.OnFailure = new LambdaDestination(errorFunction.Function, new LambdaDestinationOptions
            {
                ResponseOnly = true,
            });

问题原因与修复

1. Catch字段类型错误

你将catchSerialized序列化成了JSON字符串,但Step Functions状态定义中Catch字段要求的是数组对象,而非字符串。当前代码把字符串赋值给Catch,直接触发Schema验证失败(提示Expected value of type [ARRAY])。

2. TerminalState不可达(关联错误)

因为Catch字段类型错误,Step Functions无法识别AudienceListUserValidation的错误跳转逻辑,进而判定TerminalState未被任何状态引用,导致MISSING_TRANSITION_TARGET错误。

修复代码

将catchSerialized从JSON字符串改为对象数组,无需序列化,直接用字典结构定义:

var catchConfig = new List<Dictionary<string, object>>
{
    new Dictionary<string, object>
    {
        { "ErrorEquals", new[] { "States.ALL" } },
        { "Next", "TerminalState" }
    }
};

然后替换AudienceListUserValidation状态中的Catch配置:

{ "Catch", catchConfig },

CDK中OnFailure与Catch的区别

不能直接用Lambda的OnFailure替代Step Functions的Catch:

  • Lambda的OnFailure是Lambda函数层面的错误处理,仅当Lambda执行触发崩溃、超时等特定错误时,才会调用指定目标服务,属于函数自身配置。
  • Step Functions的Catch是工作流层面的错误处理,不仅能捕获Lambda执行错误,还能处理Step Functions状态本身的错误(如参数解析、状态跳转错误等),且能控制工作流后续走向(跳转其他状态、终止等)。

如果用CDK构建状态机,建议使用官方Step Functions构造库(aws-cdk-lib/aws-stepfunctions),更优雅地定义错误逻辑:

var validationTask = new LambdaInvoke(this, "AudienceListUserValidation", new LambdaInvokeProps
{
    LambdaFunction = userValidationfunction.Function,
    Payload = JsonPath.StringAt("$"),
    ResultPath = JsonPath.DISCARD
});

var terminalTask = new LambdaInvoke(this, "TerminalState", new LambdaInvokeProps
{
    LambdaFunction = errorFunction.Function,
    Payload = JsonPath.StringAt("$")
});

validationTask.AddCatch(terminalTask, new CatchProps
{
    Errors = new[] { "States.ALL" }
});

var mapState = new Map(this, "ProcessFile", new MapProps
{
    MaxConcurrency = 5,
    ItemProcessor = new Processor(validationTask),
    ItemReader = new S3CsvReader(new S3CsvReaderProps
    {
        Bucket = Bucket.FromBucketName(this, "FileBucket", "<your-bucket-name>"),
        Key = JsonPath.StringAt("$.S3FileName"),
        HeaderLocation = CsvHeaderLocation.FIRST_ROW
    }),
    ItemSelector = new Dictionary<string, object>
    {
        { "MatchingFieldId.$", "$$.Map.Item.Value.Email" },
        { "FileUploadId.$", "$.FileUploadId" }
    },
    ResultPath = JsonPath.DISCARD
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 20:15:12