@@ -119,6 +119,9 @@ Workflow consumers will get an instance of *WorkflowExecutionError. This error w
119
119
*/
120
120
121
121
type (
122
+ // Category of the error. Maps to logging/metrics behaviours.
123
+ ApplicationErrorCategory string
124
+
122
125
// ApplicationErrorOptions represents a combination of error attributes and additional requests.
123
126
// All fields are optional, providing flexibility in error customization.
124
127
//
@@ -137,6 +140,7 @@ type (
137
140
//
138
141
// NOTE: This option is supported by Temporal Server >= v1.24.2 older version will ignore this value.
139
142
NextRetryDelay time.Duration
143
+ Category ApplicationErrorCategory
140
144
}
141
145
142
146
// ApplicationError returned from activity implementations with message and optional details.
@@ -150,6 +154,7 @@ type (
150
154
cause error
151
155
details converter.EncodedValues
152
156
nextRetryDelay time.Duration
157
+ category ApplicationErrorCategory
153
158
}
154
159
155
160
// TimeoutError returned when activity or child workflow timed out.
@@ -380,6 +385,11 @@ var (
380
385
ErrMissingWorkflowID = errors .New ("workflow ID is unset for Nexus operation" )
381
386
)
382
387
388
+ const (
389
+ // ErrorCategoryBenign indicates an error that is expected under normal operation and should not trigger alerts.
390
+ ErrorCategoryBenign ApplicationErrorCategory = "benign"
391
+ )
392
+
383
393
// NewApplicationError create new instance of *ApplicationError with message, type, and optional details.
384
394
func NewApplicationError (msg string , errType string , nonRetryable bool , cause error , details ... interface {}) error {
385
395
return NewApplicationErrorWithOptions (
@@ -397,6 +407,7 @@ func NewApplicationErrorWithOptions(msg string, errType string, options Applicat
397
407
cause : options .Cause ,
398
408
nonRetryable : options .NonRetryable ,
399
409
nextRetryDelay : options .NextRetryDelay ,
410
+ category : options .Category ,
400
411
}
401
412
// When return error to user, use EncodedValues as details and data is ready to be decoded by calling Get
402
413
details := options .Details
@@ -661,6 +672,11 @@ func (e *ApplicationError) Unwrap() error {
661
672
// a zero value means to use the activities retry policy.
662
673
func (e * ApplicationError ) NextRetryDelay () time.Duration { return e .nextRetryDelay }
663
674
675
+ // Category returns the ApplicationErrorCategory of the error.
676
+ func (e * ApplicationError ) Category () ApplicationErrorCategory {
677
+ return e .category
678
+ }
679
+
664
680
// Error from error interface
665
681
func (e * TimeoutError ) Error () string {
666
682
msg := fmt .Sprintf ("%s (type: %s)" , e .message (), e .timeoutType )
@@ -1029,3 +1045,51 @@ func getErrType(err error) string {
1029
1045
1030
1046
return t .Name ()
1031
1047
}
1048
+
1049
+ // applicationErrorCategoryToProto converts the internal ApplicationErrorCategory to its proto representation.
1050
+ func applicationErrorCategoryToProto (category ApplicationErrorCategory ) enumspb.ApplicationErrorCategory {
1051
+ switch category {
1052
+ case ErrorCategoryBenign :
1053
+ return enumspb .APPLICATION_ERROR_CATEGORY_BENIGN
1054
+ case "" :
1055
+ // Zero value maps to unspecified
1056
+ return enumspb .APPLICATION_ERROR_CATEGORY_UNSPECIFIED
1057
+ default :
1058
+ // Fallback to unspecified if unknown case
1059
+ return enumspb .APPLICATION_ERROR_CATEGORY_UNSPECIFIED
1060
+ }
1061
+ }
1062
+
1063
+ // applicationErrorCategoryFromProto converts the proto ApplicationErrorCategory to its internal representation.
1064
+ func applicationErrorCategoryFromProto (category enumspb.ApplicationErrorCategory ) ApplicationErrorCategory {
1065
+ switch category {
1066
+ case enumspb .APPLICATION_ERROR_CATEGORY_BENIGN :
1067
+ return ErrorCategoryBenign
1068
+ case enumspb .APPLICATION_ERROR_CATEGORY_UNSPECIFIED :
1069
+ return "" // Map unspecified back to the zero value
1070
+ default :
1071
+ // Handle unknown proto values - map to the zero value (unspecified)
1072
+ // Consider logging a warning if an unexpected proto value is received.
1073
+ return ""
1074
+ }
1075
+ }
1076
+
1077
+ // IsBenignApplicationError checks if the given error is an ApplicationError
1078
+ // with the category set to CategoryBenign.
1079
+ func IsBenignApplicationError (err error ) bool {
1080
+ var appError * ApplicationError
1081
+ // Use errors.As to check type and get value simultaneously.
1082
+ // Then check if the category field matches CategoryBenign.
1083
+ return errors .As (err , & appError ) && appError .Category () == ErrorCategoryBenign
1084
+ }
1085
+
1086
+ // isBenignProtoApplicationFailure checks if the given proto Failure represents
1087
+ // an ApplicationFailure with the category set to Benign.
1088
+ func isBenignProtoApplicationFailure (failure * failurepb.Failure ) bool {
1089
+ if failure == nil {
1090
+ return false
1091
+ }
1092
+ appFailureInfo := failure .GetApplicationFailureInfo ()
1093
+ // Check if it's an ApplicationFailureInfo and if its category is Benign.
1094
+ return appFailureInfo != nil && appFailureInfo .GetCategory () == enumspb .APPLICATION_ERROR_CATEGORY_BENIGN
1095
+ }
0 commit comments