Handling activity schedule-to-close timeouts

I have a use case for catching schedule-to-close timeouts and noticed some peculiar behaviour on the errors being returned.

Say for example the schedule-to-close timeout is set to 10s. If the activity exceeds 10s in execution time, it returns a TimeoutError with a schedule-to-close timeout type. This is what I’m expecting and checking for in my activity error handling.

However, let’s say the activity executes very quickly but always returns an error, using the default retry policy. Now if I only check for the TimeoutError, the workflow fails with an ActivityError instead (because the next retry interval would already exceed the 10s schedule-to-close timeout, Temporal immediately terminates the workflow).

So in effect, to correctly catch the schedule-to-close timeout, this is what I’m using:

if err != nil {
	var actError *temporal.ActivityError
	var timeoutError *temporal.TimeoutError
	if (errors.As(err, &actError) && actError.RetryState() == enums.RETRY_STATE_TIMEOUT) ||
		(errors.As(err, &timeoutError) && timeoutError.TimeoutType() == enums.TIMEOUT_TYPE_SCHEDULE_TO_CLOSE) {
		// handle schedule-to-close timeout

Which is a little clunky and unintuitive.

Is this the expected way to check for schedule-to-close timeouts? I would’ve thought that it makes more sense returning the schedule-to-close TimeoutError in all cases where the activity doesn’t continue as a result of schedule-to-close timeout, instead of having to check for a separate ActivityError with a timeout retry state as well.