

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 處理 Step Functions 工作流程中的錯誤
<a name="concepts-error-handling"></a>

除了 `Pass`和 狀態之外，所有`Wait`狀態都可能遇到執行時間錯誤。錯誤可能因各種原因而發生，包括下列項目：
+ **狀態機器定義問題** - 例如沒有相符規則的選擇狀態
+ **任務失敗** - 例如 AWS Lambda 函數中的例外狀況
+ **暫時性問題** - 例如網路分割區事件

當狀態報告錯誤時，Step Functions 預設會讓**整個**狀態機器執行失敗。Step Functions 也有更進階的錯誤處理功能。您可以設定狀態機器來擷取錯誤、重試失敗狀態，以及正常實作錯誤處理通訊協定。

Step Functions 擷取器可用於**任務**、**平行**和**映射**狀態，但不適用於頂層狀態機器執行失敗。為了處理您預期可能會失敗的執行，您的發起人可以處理錯誤，或者您可以將這些執行巢狀化在子工作流程中，以擷取父工作流程中的錯誤。或者，您可以選擇使用 EventBridge 匯流排接聽標準工作流程`TIMED_OUT`的事件，並叫用 動作來處理失敗的執行。

**處理錯誤的實際範例**  
若要部署包含錯誤處理之工作流程的範例，請參閱本指南中的[在 Step Functions 狀態機器中處理錯誤條件](tutorial-handling-error-conditions.md)教學課程，以及* AWS Step Functions 研討會*中的[錯誤處理](https://catalog.workshops.aws/stepfunctions/handling-errors)。

## 錯誤名稱
<a name="error-handling-error-representation"></a>

Step Functions 使用區分大小寫的字串識別錯誤，稱為*錯誤名稱*。Amazon States Language 會定義一組內建字串，命名已知的錯誤，所有錯誤都以 `States.` 字首開頭。

狀態可以回報具有其他名稱的錯誤。不過，錯誤名稱不能以字`States.`首開頭。

確保您的生產程式碼可以處理 AWS Lambda 服務例外狀況 (`Lambda.ServiceException` 和 `Lambda.SdkClientException`)。如需詳細資訊，請參閱 *最佳實務*[處理暫時性 Lambda 服務例外狀況](sfn-best-practices.md#bp-lambda-serviceexception)中的 。

** `States.ALL` **  
符合任何已知錯誤名稱的萬用字元。  
`States.ALL` 錯誤類型必須單獨出現在 中，`Catcher`且無法捕捉`States.DataLimitExceeded`終端錯誤或`Runtime`錯誤類型。  
如需詳細資訊，請參閱[`States.DataLimitExceeded`](#error-data-limit-exceed)及[`States.Runtime`](#states-runtime-error)。

** `States.DataLimitExceeded` **  
錯誤類型無法攔截的終端機`States.ALL`錯誤。  
由於下列條件而報告：  
+ 連接器的輸出大於承載大小配額。
+ 狀態的輸出大於承載大小配額。
+ `Parameters` 處理後，狀態的輸入大於承載大小配額。
如需配額的詳細資訊，請參閱 [Step Functions 服務配額](service-quotas.md)。

**`States.ExceedToleratedFailureThreshold`**  
`Map` 狀態失敗，因為失敗項目的數量超過狀態機器定義中指定的閾值。如需詳細資訊，請參閱[在 Step Functions 中設定分散式映射狀態的失敗閾值](state-map-distributed.md#maprun-fail-threshold)。

** `States.HeartbeatTimeout` **  
`Task` 狀態無法在超過 `HeartbeatSeconds`值的期間內傳送活動訊號。  
`HeartbeatTimeout` 可在 `Catch`和 `Retry` 欄位中使用。

** `States.Http.Socket` **  
當 HTTP 任務在 60 秒後逾時時發生。請參閱 [與 HTTP 任務相關的配額](service-quotas.md#service-limits-http-task)。

**`States.ItemReaderFailed`**  
`Map` 狀態失敗，因為無法從 `ItemReader` 欄位中指定的項目來源讀取。如需詳細資訊，請參閱`ItemReader （地圖）`。

** `States.Permissions` **  
`Task` 狀態失敗，因為其權限不足，無法執行指定的程式碼。

**`States.ResultWriterFailed`**  
`Map` 狀態失敗，因為它無法將結果寫入 `ResultWriter` 欄位中指定的目的地。如需詳細資訊，請參閱`ResultWriter （地圖）`。

**`States.Runtime`**  
由於某些無法處理的例外狀況，導致執行失敗。這些通常是在運行時間的錯誤所導致，例如嘗試在 Null JSON 承載上套用 `InputPath` 或 `OutputPath`。`States.Runtime` 錯誤無法重試，且一律會導致執行失敗。重試或擷取`States.ALL`不會擷取`States.Runtime`錯誤。

** `States.TaskFailed` **  
在執行期間失敗的 `Task` 狀態。在重試或擷取中使用時， `States.TaskFailed` 會做為萬用字元，以比對 以外的任何已知錯誤名稱`States.Timeout`。

** `States.Timeout` **  
  
當`Task`狀態執行時間超過 `TimeoutSeconds`值，或無法傳送活動訊號的時間超過 `HeartbeatSeconds`值時回報。  
如果*巢狀狀態機器*擲回 `States.Timeout`，父系會收到`States.TaskedFailed`錯誤。  
當整個狀態機器執行執行時間超過指定的`TimeoutSeconds`值時，也會報告`States.Timeout`錯誤。

**注意**  
Lambda 執行時間中未處理的錯誤歷史上僅報告為 `Lambda.Unknown`。在較新的執行時間中，逾時會在錯誤輸出`Sandbox.Timedout`中回報為 。  
當 Lambda 超過調用數量上限時，報告的錯誤將為 `Lambda.TooManyRequestsException`。  
在 `Lambda.Unknown`、 `Sandbox.Timedout`和 上進行比對`States.TaskFailed`，以處理可能的錯誤。您也可以使用 `States.ALL`，但必須是單獨且位於清單結尾。  
如需 Lambda `Handled`和`Unhandled`錯誤的詳細資訊，請參閱《 [AWS Lambda 開發人員指南](https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html#API_Invoke_ResponseSyntax)`FunctionError`》中的 。

## 發生錯誤後重試
<a name="error-handling-retrying-after-an-error"></a>

`Task`、 `Parallel`和 `Map` 狀態可以有一個名為 的欄位`Retry`，其值必須是稱為*重試器*的物件陣列。個別重試器代表特定重試次數，通常採取增量時間間隔。

當其中一個狀態回報錯誤且有 `Retry` 欄位時，Step Functions 會依陣列中列出的順序掃描重試器。當錯誤名稱出現在重試器`ErrorEquals`欄位的值中時，狀態機器會依 `Retry` 欄位所定義進行重試嘗試。

如果您的redriven執行重新執行您已定義[重試](#error-handling-retrying-after-an-error)的 [任務工作流程狀態](state-task.md)、 [平行工作流程狀態](state-parallel.md)或[內嵌映射狀態](state-map-inline.md)，則這些狀態的重試嘗試計數會重設為 0，以允許 上的最大嘗試次數redrive。對於redriven執行，您可以使用 主控台追蹤這些狀態的個別重試嘗試。如需詳細資訊，請參閱 [在 Step Functions redrive中使用 重新啟動狀態機器執行](redrive-executions.md) 中的 [redriven 執行的重試行為](redrive-executions.md#redrive-retry-behavior)。

Retrier 包含下列欄位：

** `ErrorEquals` (必要)**  
符合錯誤名稱的非空白字串陣列。當狀態報告錯誤時，Step Functions 會掃描重試器。當錯誤名稱出現於此陣列時，它會實作此 Retrier 中所述的重試政策。

** `IntervalSeconds` (選用)**  
正整數，代表第一次重試嘗試之前的秒數 (`1`預設為 )。 `IntervalSeconds` 的最大值為 99999999。

** `MaxAttempts` (選用)**  
正整數，其代表重試次數上限 (預設值 `3`)。如果出現錯誤的次數超過指定次數，則重試會停止且一般錯誤處理會繼續執行。值 `0`指定永遠不會重試錯誤。 `MaxAttempts` 的最大值為 99999999。

** `BackoffRate` (選用)**  
每次重試嘗試後，以 表示的重試間隔`IntervalSeconds`增加的乘數。依預設，`BackoffRate` 值會依 `2.0` 增加。  
例如，假設您的 `IntervalSeconds`是 3， `MaxAttempts`是 3， `BackoffRate`是 2。第一次重試嘗試會在錯誤發生後三秒進行。第二次重試會在第一次重試嘗試的六秒後進行。而第三次重試會在第二次重試嘗試後 12 秒進行。

** `MaxDelaySeconds` (選用) **  
設定最大值的正整數，以秒為單位，最多可增加重試間隔。此欄位有助於與 `BackoffRate` 欄位搭配使用。您在此欄位中指定的值會限制因套用至每次連續重試嘗試的退避率乘數所產生的指數等待時間。您必須為 指定大於 0 且小於 31622401 的值`MaxDelaySeconds`。  
如果您未指定此值，Step Functions 不會限制重試嘗試之間的等待時間。

** `JitterStrategy` (選用) **  
此字串決定是否要在連續重試嘗試之間的等待時間中包含抖動。抖動透過在隨機延遲間隔中分散這些嘗試來減少同時重試嘗試。此字串接受 `FULL`或 `NONE`作為其值。預設值為 `NONE`。  
例如，假設您已`MaxAttempts`將 設定為 3、`IntervalSeconds`將 設定為 2，並將 `BackoffRate`設定為 2。第一次重試嘗試會在發生錯誤後兩秒進行。第二次重試會在第一次重試後四秒進行，而第三次重試會在第二次重試後八秒進行。如果您`JitterStrategy`將 設定為 `FULL`，則第一個重試間隔會在 0 到 2 秒之間隨機化，第二個重試間隔會在 0 到 4 秒之間隨機化，第三個重試間隔會在 0 到 8 秒之間隨機化。

**注意**  
重試視為狀態轉換。如需狀態轉換如何影響帳單的資訊，請參閱 [Step Functions 定價](https://aws.amazon.com/step-functions/pricing/)。

### 重試欄位範例
<a name="retry-field-examples"></a>

本節包含下列`Retry`欄位範例。
+ [Retry with BackoffRate](#retrybackoffrate)
+ [Retry with MaxDelaySeconds](#retrymaxdelayseconds)
+ [Retry all errors except States.Timeout](#retrytimeout)
+ [Complex retry scenario](#complexretryeg)

**範例 1 – 使用 BackoffRate 重試**  
下列 範例`Retry`會進行兩次重試嘗試，第一次重試會在等待三秒後進行。根據您`BackoffRate`指定的 ，Step Functions 會增加每次重試之間的間隔，直到達到重試次數上限為止。在下列範例中，第二次重試嘗試會在第一次重試後等待三秒後開始。

```
"Retry": [ {
   "ErrorEquals": [ "States.Timeout" ],
   "IntervalSeconds": 3,
   "MaxAttempts": 2,
   "BackoffRate": 1
} ]
```

**範例 2 – 使用 MaxDelaySeconds 重試**  
下列範例會進行三次重試嘗試，並將 產生的等待時間限制`BackoffRate`在 5 秒。第一次重試會在等待三秒後進行。由於 `MaxDelaySeconds` 設定了等待時間上限，因此第二次和第三次重試會在前一次重試後等待五秒才進行。

```
"Retry": [ {
    "ErrorEquals": [ "States.Timeout" ],
    "IntervalSeconds": 3,
    "MaxAttempts": 3,
    "BackoffRate":2,
    "MaxDelaySeconds": 5,
    "JitterStrategy": "FULL"
} ]
```

若未設定 `MaxDelaySeconds`，則第二次重試會在第一次重試後 6 秒進行，而第三次重試會在第二次重試後 12 秒後才進行。

**範例 3 – 重試 States.Timeout 以外的所有錯誤**  
出現在 Retrier 的 `ErrorEquals` 欄位中的預留名稱 `States.ALL` 是符合任何錯誤名稱的萬用字元。它必須單獨顯示在 `ErrorEquals` 陣列中，而且必須顯示在 `Retry` 陣列的最後一個 Retrier 中。此名稱`States.TaskFailed`也會作用萬用字元，並符合 以外的任何錯誤`States.Timeout`。

下列`Retry`欄位範例會重試除 以外的任何錯誤`States.Timeout`。

```
"Retry": [ {
   "ErrorEquals": [ "States.Timeout" ],
   "MaxAttempts": 0
}, {
   "ErrorEquals": [ "States.ALL" ]
} ]
```

**範例 4 – 複雜重試案例**  
Retrier 的參數會套用於在單一狀態執行的範疇中對 Retrier 的所有造訪。

請考慮以下 `Task` 狀態。

```
"X": {
   "Type": "Task",
   "Resource": "arn:aws:states:region:123456789012:task:X",
   "Next": "Y",
   "Retry": [ {
      "ErrorEquals": [ "ErrorA", "ErrorB" ],
      "IntervalSeconds": 1,
      "BackoffRate": 2.0,
      "MaxAttempts": 2
   }, {
      "ErrorEquals": [ "ErrorC" ],
      "IntervalSeconds": 5
   } ],
   "Catch": [ {
      "ErrorEquals": [ "States.ALL" ],
      "Next": "Z"
   } ]
}
```

此任務連續失敗四次，輸出這些錯誤名稱：`ErrorA`、`ErrorC`、 `ErrorB`和 `ErrorB`。因此會發生下列情況：
+ 前兩個錯誤符合第一個重試器，並導致等待一秒和兩秒。
+ 第三個錯誤符合第二個重試器，並導致等待 5 秒。
+ 第四個錯誤也符合第一個重試器。不過，已達該特定錯誤的兩次重試次數上限 (`MaxAttempts`)。因此，該重試器失敗，執行會透過 `Catch` 欄位將工作流程重新導向至 `Z` 狀態。

## 後援狀態
<a name="error-handling-fallback-states"></a>

`Task`、 `Map`和 `Parallel` 狀態各自可以有一個名為 的欄位`Catch`。此欄位的值必須物件陣列，也稱為 Catcher**。

Catcher 包含下列欄位。

** `ErrorEquals` (必要)**  
符合錯誤名稱的非空白字串陣列，其指定方式完全與同名的 Retrier 欄位一樣。

** `Next` (必要)**  
字串，該字串必須完全符合其中一個狀態機器的狀態名稱。

** `ResultPath` (JSONPath，選用）**  
決定擷取器傳送至 `Next` 欄位中指定狀態的輸入[路徑](concepts-input-output-filtering.md)。

當狀態回報錯誤且沒有`Retry`欄位，或重試無法解決錯誤時，Step Functions 會依陣列中列出的順序掃描擷取器。當錯誤名稱顯示於 Catcher 的 `ErrorEquals` 欄位值時，狀態機器會轉換到 `Next` 欄位中具名的狀態。

出現在 Catcher 的 `ErrorEquals` 欄位中的預留名稱 `States.ALL` 是符合任何錯誤名稱的萬用字元。它必須單獨顯示在 `ErrorEquals` 陣列中，而且必須顯示在 `Catch` 陣列的最後一個 Catcher 中。此名稱`States.TaskFailed`也會作用萬用字元，並符合 以外的任何錯誤`States.Timeout`。

以下 `Catch` 欄位範例會在 Lambda 函式輸出未處理的 Java 例外狀況時，轉換成名為 `RecoveryState` 的狀態。否則，此欄位會轉換到 `EndState` 狀態。

```
"Catch": [ {
   "ErrorEquals": [ "java.lang.Exception" ],
   "ResultPath": "$.error-info",
   "Next": "RecoveryState"
}, {
   "ErrorEquals": [ "States.ALL" ],
   "Next": "EndState"
} ]
```

**捕捉器可以捕捉多少錯誤？**  
每個擷取器可以指定要處理的**多個錯誤**。

### 錯誤輸出
<a name="error-handling-error-output"></a>

當 Step Functions 轉換為擷取名稱中指定的狀態時，物件通常包含 欄位 `Cause`。此欄位的值是人類可讀的錯誤描述。此物件也稱為「錯誤輸出」**。

在先前的 JSONPath 範例中，第一個擷取器包含 `ResultPath` 欄位。其運作方式類似於狀態最上層中的 `ResultPath` 欄位，會造成兩種可能性：
+ 取得該狀態執行的結果，並覆寫狀態輸入的所有或部分。
+ 取得結果並將其新增至輸入。如果擷取器處理錯誤，狀態執行的結果即為錯誤輸出。

因此，對於範例中的第一個擷取器，`error-info`如果輸入中還沒有具有此名稱的欄位，則擷取器會將錯誤輸出新增至輸入，做為名為 的欄位。然後，擷取器會將整個輸入傳送至 `RecoveryState`。對於第二個擷取器，錯誤輸出會覆寫輸入，而擷取器只會將錯誤輸出傳送至 `EndState`。

對於 JSONPath 工作流程，如果您未指定 `ResultPath` 欄位，它會預設為 `$`，這會選取並覆寫整個輸入。

當狀態同時具有 `Retry`和 `Catch` 欄位時，Step Functions 會先使用任何適當的重試器。如果重試政策無法解決錯誤，Step Functions 會套用相符的擷取器轉換。

### 造成承載和服務整合
<a name="error-handling-integrations-json"></a>

擷取器會傳回字串承載做為輸出。使用 Amazon Athena 或 等服務整合時 AWS CodeBuild，您可能想要將`Cause`字串轉換為 JSON。下列具有內部函數`Pass`的狀態範例示範如何將`Cause`字串轉換為 JSON。

```
"Handle escaped JSON with JSONtoString": {
  "Type": "Pass",
  "Parameters": {
    "Cause.$": "States.StringToJson($.Cause)"
  },
  "Next": "Pass State with Pass Processing"
},
```

## 使用重試和擷取的狀態機器範例
<a name="error-handling-examples"></a>

下列範例中定義的狀態機器假設存在兩個 Lambda 函數：一個一律失敗，另一個等待足夠長的時間，以允許狀態機器中定義的逾時發生。

這是 Node.js Lambda 函數的定義，一律失敗，並傳回訊息 `error`。在下列狀態機器範例中，此 Lambda 函數名為 `FailFunction`。如需建立 Lambda 函數的詳細資訊，請參閱[步驟 1：建立 Lambda 函式](tutorial-creating-lambda-state-machine.md#create-lambda-function)一節。

```
exports.handler = (event, context, callback) => {
    callback("error");
};
```

這是 Node.js Lambda 函數的定義，會休眠 10 秒。在下列狀態機器範例中，此 Lambda 函數名為 `sleep10`。

```
exports.handler = (event, context, callback) => {
    setTimeout(function(){
    }, 11000);
};
```

**函數的逾時設定**  
當您為範例建立 Lambda 函數時，請記得將進階設定中的`Timeout`值設定為 11 秒。

### 使用重試處理失敗
<a name="error-handling-handling-failure-using-retry"></a>

此狀態機器會使用 `Retry` 欄位來重試失敗且輸出錯誤名稱 `HandledError` 的函數。它會在重試之間以指數退避的方式重試此函數兩次。

```
{
   "Comment": "A Hello World example invoking Lambda function",
   "StartAt": "HelloWorld",
   "States": {
      "HelloWorld": {
         "Type": "Task",
         "Resource": "arn:aws:lambda:region:123456789012:function:FailFunction",
         "Retry": [ {
            "ErrorEquals": ["HandledError"],
            "IntervalSeconds": 1,
            "MaxAttempts": 2,
            "BackoffRate": 2.0
         } ],
      "End": true
      }
   }
}
```

此變體使用預先定義的錯誤代碼 `States.TaskFailed`，這符合 Lambda 函數輸出的任何錯誤。

```
{
   "Comment": "Hello World example which invokes a AWS Lambda function",
   "StartAt": "HelloWorld",
   "States": {
      "HelloWorld": {
         "Type": "Task",
         "Resource": "arn:aws:lambda:region:123456789012:function:FailFunction",
         "Retry": [ {
            "ErrorEquals": ["States.TaskFailed"],
            "IntervalSeconds": 1,
            "MaxAttempts": 2,
            "BackoffRate": 2.0
         } ],
         "End": true
      }
   }
}
```

**處理 Lambda 例外狀況的最佳實務**  
參考 Lambda 函數的任務應處理 Lambda 服務例外狀況。如需詳細資訊，請參閱 最佳實務[處理暫時性 Lambda 服務例外狀況](sfn-best-practices.md#bp-lambda-serviceexception)中的 。

### 使用 Catch 處理失敗
<a name="error-handling-handling-failure-using-catch"></a>

此範例會使用 `Catch` 欄位。當 Lambda 函數輸出錯誤時，它會擷取錯誤，且狀態機器會轉換為 `fallback` 狀態。

```
{
   "Comment": "Hello World example which invokes a AWS Lambda function",
   "StartAt": "HelloWorld",
   "States": {
      "HelloWorld": {
         "Type": "Task",
         "Resource": "arn:aws:lambda:region:123456789012:function:FailFunction",
         "Catch": [ {
            "ErrorEquals": ["HandledError"],
            "Next": "fallback"
         } ],
         "End": true
      },
      "fallback": {
         "Type": "Pass",
         "Result": "Hello, AWS Step Functions!",
         "End": true
      }
   }
}
```

此變體使用預先定義的錯誤代碼 `States.TaskFailed`，這符合 Lambda 函數輸出的任何錯誤。

```
{
   "Comment": "Hello World example which invokes a AWS Lambda function",
   "StartAt": "HelloWorld",
   "States": {
      "HelloWorld": {
         "Type": "Task",
         "Resource": "arn:aws:lambda:region:123456789012:function:FailFunction",
         "Catch": [ {
            "ErrorEquals": ["States.TaskFailed"],
            "Next": "fallback"
         } ],
      "End": true
      },
      "fallback": {
         "Type": "Pass",
         "Result": "Hello, AWS Step Functions!",
         "End": true
      }
   }
}
```

### 使用重試處理逾時
<a name="error-handling-handling-timeout-using-retry"></a>

此狀態機器會根據 中指定的逾時值，使用 `Retry` 欄位重試逾時`Task`的狀態`TimeoutSeconds`。Step Functions 會在此`Task`狀態下重試 Lambda 函數呼叫兩次，重試之間會有指數退避。

```
{
   "Comment": "Hello World example which invokes a AWS Lambda function",
   "StartAt": "HelloWorld",
   "States": {
      "HelloWorld": {
         "Type": "Task",
         "Resource": "arn:aws:lambda:region:123456789012:function:sleep10",
         "TimeoutSeconds": 2,
         "Retry": [ {
            "ErrorEquals": ["States.Timeout"],
            "IntervalSeconds": 1,
            "MaxAttempts": 2,
            "BackoffRate": 2.0
         } ],
         "End": true
      }
   }
}
```

### 使用 Catch 處理逾時
<a name="error-handling-handling-timeout-using-catch"></a>

此範例會使用 `Catch` 欄位。如果發生逾時，狀態機器就會轉換到 `fallback` 狀態。

```
{
   "Comment": "Hello World example which invokes a AWS Lambda function",
   "StartAt": "HelloWorld",
   "States": {
      "HelloWorld": {
         "Type": "Task",
         "Resource": "arn:aws:lambda:region:123456789012:function:sleep10",
         "TimeoutSeconds": 2,
         "Catch": [ {
            "ErrorEquals": ["States.Timeout"],
            "Next": "fallback"
         } ],
         "End": true
      },
      "fallback": {
         "Type": "Pass",
         "Result": "Hello, AWS Step Functions!",
         "End": true
      }
   }
}
```

**在 JSONPath 中保留狀態輸入和錯誤**  
在 JSONPath 中，您可以使用 保留狀態輸入和錯誤`ResultPath`。請參閱[使用 ResultPath 在 中同時包含錯誤和輸入 `Catch`](input-output-resultpath.md#input-output-resultpath-catch)。