Can I use a struct containing error as application error details field?

Hi,

I am trying to use a UserError which contains an error type field, it looks like the below:

type Error struct {
	// Type of the error.
	Type string

	// The cause of the error, and more detail if available.
	Cause  string
	Detail error
}

which itself is an error type as well with the Error() method:

// Error turns the service error into a string.
func (re *Error) Error() string {
	var sb strings.Builder
	sb.WriteString(re.Cause)
	if re.Detail != nil {
		sb.WriteString(": ")
		sb.WriteString(re.Detail.Error())
	}
	return sb.String()
}

Here’s how I inspect the error in the defer function and return the application error:

// ParseError inspects and return either a retryable error or a non-retryable error.
func ParseError(errMessage string, err error) error {
	if err == nil {
		return nil
	}
	var xError *Error
	if errors.As(err, &xRapidError) {
		return temporal.NewNonRetryableApplicationError(errMessage, xError.Type, nil, xError)
	}
	return temporal.NewNonRetryableApplicationError(errMessage, xError.Type, nil, err)
}

But it seems like when an application error was returned, the detail disappeared. Any thoughts on that?

You cannot pass application specific failures across process boundaries. Any non temporal error is converted to an ApplicationError. You can attach any application specific information to that error as details.

See Returning partial results from activity on error and Temporal Failures | Temporal Documentation

Thanks for the quick response, sorry for not explaining clear enough (Sorry for confusion of naming my struct as Error, and include fields like Cause and Detail similar to the one in ApplicationError). After execution of the activity, I did try to use a unwrap function to unwrap the application error and get back what is within the detail

// UnwrapError extracts the original error from a typeless error. In particular, Temporal wraps the
// errors returned by activities and workflows in its own objects that we want to get back.
func UnwrapError(err error) *Error {
	if err == nil {
		return nil
	}

	// Check if the error is an Error type error.
	var xErr *Error
	if errors.As(err, &xErr) {
		return xErr
	}

	// Check if we received a generic application error.
	var appErr *temporal.ApplicationError
	if errors.As(err, &appErr) {
		// Try to get the error if it is embedded in the details field.
		if appErr.Details(&xErr) == nil {
			return xErr
		}
	}

	// Return the unknown error as it is.
	return &Error{
		Cause: err.Error(),
	}
}

but it didn’t work and didn’t get back the Error struct detail to me if in my Error struct, the Detail field is an error type. Unless, I change the Detail field to be string, everything works fine. Any ideas for what’s happening behind? Is it true that I cannot put a error type field into the Detail of applicationError

You cannot put interface types into structures passed across the wire. The serialized JSON doesn’t contain type information and doesn’t know to which exact type to deserialize.