Skip to content

Commit a4fc69f

Browse files
yuandrewlennessyy
andauthored
Go: Don't recover from a panic in a defer (#4311)
* don't recover from a panic in a defer * make it its own section * docs: merge go error handling page * docs: add some additional go context * docs: make more succinct * fix up some existing issues --------- Co-authored-by: Lenny Chen <lenny.chen@temporal.io> Co-authored-by: Lenny Chen <55669665+lennessyy@users.noreply.github.com>
1 parent 5ba09a0 commit a4fc69f

3 files changed

Lines changed: 76 additions & 77 deletions

File tree

docs/develop/go/error-handling.mdx

Lines changed: 0 additions & 75 deletions
This file was deleted.

docs/develop/go/failure-detection.mdx

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,97 @@ sidebar_label: Failure detection
55
toc_max_heading_level: 4
66
keywords:
77
- failure detection
8+
- error-handling
89
tags:
910
- Activities
1011
- Workflows
1112
- Failures
1213
- Errors
1314
- Go SDK
1415
- Temporal SDKs
15-
description: Configure Workflow timeouts, set Retry Policies, and manage Activity timeouts and Heartbeats using Temporal's Go SDK for optimized execution control.
16+
description: Handle errors, configure Workflow timeouts, set Retry Policies, and manage Activity timeouts and Heartbeats using Temporal's Go SDK.
1617
---
1718

1819
This page shows how to do the following:
1920

21+
- [Handle errors](#error-handling)
2022
- [Set Workflow timeouts](#workflow-timeouts)
2123
- [Set a Workflow Retry Policy](#workflow-retries)
2224
- [Set Activity timeouts](#activity-timeouts)
2325
- [Set a custom Activity Retry Policy](#activity-retries)
2426

27+
## Error handling {#error-handling}
28+
29+
Within a Workflow, an Activity or Child Workflow execution might fail. You can
30+
handle errors differently based on the error type.
31+
32+
If the Activity returns an error as `errors.New()` or `fmt.Errorf()`, that error is converted into `*temporal.ApplicationError`.
33+
34+
If the Activity returns an error as `temporal.NewNonRetryableApplicationError("error message", details)`, that error is returned as `*temporal.ApplicationError`.
35+
36+
There are other types of errors such as `*temporal.TimeoutError`, `*temporal.CanceledError` and
37+
`*temporal.PanicError`.
38+
39+
Here's an example of handling Activity errors within Workflow code that differentiates between different error types.
40+
41+
```go
42+
err := workflow.ExecuteActivity(ctx, YourActivity, ...).Get(ctx, nil)
43+
if err != nil {
44+
var applicationErr *ApplicationError
45+
if errors.As(err, &applicationErr) {
46+
// retrieve error message
47+
workflow.GetLogger(ctx).Info("Application error", "error", applicationErr.Error())
48+
49+
// handle Activity errors (created via NewApplicationError() API)
50+
var detailMsg string // assuming Activity return error by NewApplicationError("message", true, "string details")
51+
applicationErr.Details(&detailMsg) // extract strong typed details
52+
53+
// handle Activity errors (errors created other than using NewApplicationError() API)
54+
switch applicationErr.Type() {
55+
case "CustomErrTypeA":
56+
// handle CustomErrTypeA
57+
case CustomErrTypeB:
58+
// handle CustomErrTypeB
59+
default:
60+
// newer version of Activity could return new errors that Workflow was not aware of.
61+
}
62+
}
63+
64+
var canceledErr *CanceledError
65+
if errors.As(err, &canceledErr) {
66+
// handle cancellation
67+
}
68+
69+
var timeoutErr *TimeoutError
70+
if errors.As(err, &timeoutErr) {
71+
// handle timeout, could check timeout type by timeoutErr.TimeoutType()
72+
switch err.TimeoutType() {
73+
case commonpb.ScheduleToStart:
74+
// Handle ScheduleToStart timeout.
75+
case commonpb.StartToClose:
76+
// Handle StartToClose timeout.
77+
case commonpb.Heartbeat:
78+
// Handle heartbeat timeout.
79+
default:
80+
}
81+
}
82+
83+
var panicErr *PanicError
84+
if errors.As(err, &panicErr) {
85+
// handle panic, message and call stack are available by panicErr.Error() and panicErr.StackTrace()
86+
}
87+
}
88+
```
89+
90+
### Panics and deferred functions
91+
92+
In Go, [`defer` schedules cleanup functions and `recover()` catches panics](https://go.dev/blog/defer-panic-and-recover) to prevent them from crashing the program.
93+
This doesn't work the same way in Temporal Workflow code — you cannot `recover()` from a panic inside a `defer`.
94+
Deferred functions that try to interact with the Temporal SDK during panic unwinding will re-panic immediately.
95+
96+
Use `defer` only for local cleanup.
97+
Handle Temporal API cleanup through explicit error checks instead.
98+
2599
## Workflow timeouts {#workflow-timeouts}
26100

27101
**How to set Workflow timeouts using the Temporal Go SDK**

vercel.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@
306306
},
307307
{
308308
"source": "/go-error-handling",
309-
"destination": "/develop/go/error-handling",
309+
"destination": "/develop/go/failure-detection#error-handling",
310310
"permanent": true
311311
},
312312
{

0 commit comments

Comments
 (0)