What are you really trying to do?
Preserve the native Error.cause chain when an Activity throws a non-ApplicationFailure error.
The Activity worker first calls ensureApplicationFailure(error), then sends the result through the configured failure converter. DefaultFailureConverter already serializes TemporalFailure.cause, but ensureApplicationFailure currently copies only the error's message, type, and stack. As a result, the cause is lost before serialization.
This affects errors from libraries that wrap their underlying error with Error.cause. For example, a database wrapper error may retain the SQL query in its own message while the actionable PostgreSQL error exists only in cause.
Minimal reproduction
export async function activity(): Promise<void> {
const databaseError = new Error('connection terminated unexpectedly');
throw new Error('query failed', { cause: databaseError });
}
The resulting Activity failure contains the outer ApplicationFailure("query failed"), but not the nested "connection terminated unexpectedly" failure.
Expected behavior
When converting a non-ApplicationFailure Error, ensureApplicationFailure should preserve error.cause when it is an Error. The existing failure converter will then serialize the nested failure using the standard Temporal failure cause field.
This is intentionally narrower than #1734: it does not map AggregateError.errors, repurpose details, or change protobuf schemas.
What are you really trying to do?
Preserve the native
Error.causechain when an Activity throws a non-ApplicationFailureerror.The Activity worker first calls
ensureApplicationFailure(error), then sends the result through the configured failure converter.DefaultFailureConverteralready serializesTemporalFailure.cause, butensureApplicationFailurecurrently copies only the error's message, type, and stack. As a result, the cause is lost before serialization.This affects errors from libraries that wrap their underlying error with
Error.cause. For example, a database wrapper error may retain the SQL query in its own message while the actionable PostgreSQL error exists only incause.Minimal reproduction
The resulting Activity failure contains the outer
ApplicationFailure("query failed"), but not the nested"connection terminated unexpectedly"failure.Expected behavior
When converting a non-
ApplicationFailureError,ensureApplicationFailureshould preserveerror.causewhen it is anError. The existing failure converter will then serialize the nested failure using the standard Temporal failurecausefield.This is intentionally narrower than #1734: it does not map
AggregateError.errors, repurposedetails, or change protobuf schemas.