Skip to content

Errors ​

Every error class, the channel it rides, and where it comes from.

The two shapes ​

temporal-contract errors come in two families.

TaggedError classes carry a _tag discriminant used by unthrown's exhaustive matcher. Tags are namespaced with the package scope ("@temporal-contract/…") so they never collide with your own or another library's. .name stays the bare class name for readable logs.

The snippets on this page are shape fragments, not runnable programs. P is unthrown's pattern namespace throughout — import { P } from "unthrown".

typescript
matcher.with(P.tag("@temporal-contract/WorkflowFailedError"), (error) => ...);

ValidationError subclasses extend Temporal's ApplicationFailure instead. This is deliberate: Temporal's terminal-failure semantics depend on it, so a validation failure fails the task permanently rather than retrying forever. They carry the concrete subclass name as the failure type, which is what survives serialization, and expose issues for in-process inspection.

typescript
if (error instanceof WorkflowInputValidationError) {
  console.error(error.issues);
}

The three channels ​

ChannelContains
okSuccess
errAnticipated domain failures — branch on these
defectUnanticipated failures — bugs, infrastructure faults

Since 8.0, TechnicalError and RuntimeClientError ride the defect channel and appear in no modeled error union. See The result model.

Contract errors ​

From @temporal-contract/contract/errors; re-exported by the worker and client.

ContractError ​

_tag: "@temporal-contract/ContractError" · channel: err

A domain error declared on a contract's errors map. One class covers every declared error; errorName is the discriminant.

PropertyType
errorNamethe declared key, and the ApplicationFailure.type on the wire
datapayload, validated against the declared schema
messageoverridable per instance
causeoptional
typescript
matcher.with(P.tag("@temporal-contract/ContractError"), (error) => {
  switch (error.errorName) {
    case "CardDeclined":
      return error.data.reason;
  }
});

Surfaces on the workflow side when calling an errors-declaring activity, and on the client side when awaiting a workflow that declares errors.

Related types: AnyContractError, ContractErrorUnion, ContractErrorInputUnion, ContractErrorConstructors, ContractErrorOptions.

TechnicalError ​

_tag: "@temporal-contract/TechnicalError" · channel: defect only

An infrastructure fault — a connection failure, a workflow bundle that will not compile. Never appears in a modeled E channel; it is only ever a defect's cause.

PropertyType
messagedescriptive
causethe underlying failure
typescript
const result = await TypedWorker.create({ ... });
if (result.isDefect() && result.cause instanceof TechnicalError) {
  console.error(result.cause.message, result.cause.cause);
}

Client errors ​

From @temporal-contract/client.

RuntimeClientError ​

_tag: "@temporal-contract/RuntimeClientError" · channel: defect only

A technical failure with no more specific class — an unrecognized Temporal rejection, a transport error.

PropertyType
operationthe operation that failed
causethe underlying failure

WorkflowNotInContractError ​

_tag: "@temporal-contract/WorkflowNotInContractError" · channel: err

The workflow name is not on the contract. A programming error, not a runtime condition.

PropertyType
workflowNamestring
availableWorkflowsstring[]

From startWorkflow, executeWorkflow, signalWithStart, getHandle, schedule.create.

WorkflowExecutionNotFoundError ​

_tag: "@temporal-contract/WorkflowExecutionNotFoundError" · channel: err

The targeted execution does not exist in the namespace. Distinct from WorkflowNotInContractError above.

PropertyType
workflowIdstring
runIdstring | undefined
causeunknown

From every handle method, and from executeWorkflow when the execution goes missing mid-flight.

WorkflowAlreadyStartedError ​

_tag: "@temporal-contract/WorkflowAlreadyStartedError" · channel: err

Starting collided with an existing execution. Usually a workflow-id reuse policy rejecting a duplicate while a previous run is still in retention.

PropertyType
workflowTypestring
workflowIdstring
causeunknown

Branch on this to make a start idempotent — fetch the existing handle and continue.

ScheduleAlreadyExistsError ​

_tag: "@temporal-contract/ScheduleAlreadyExistsError" · channel: err

schedule.create collided with an existing (running, not deleted) schedule under the same id. Branch on it for create-if-absent semantics.

PropertyType
scheduleIdstring
causeunknown

ScheduleNotFoundError ​

_tag: "@temporal-contract/ScheduleNotFoundError" · channel: err

The schedule id is unknown to the Temporal server — wrong id, or the schedule was deleted. From every TypedScheduleHandle method.

PropertyType
scheduleIdstring
causeunknown

WorkflowFailedError ​

_tag: "@temporal-contract/WorkflowFailedError" · channel: err

The workflow completed with a failure.

PropertyType
workflowIdstring
causeTemporalFailure | undefined — unwrapped

cause is the underlying TemporalFailure lifted out of Temporal's wrapper, so you can branch in one step:

typescript
if (error.cause instanceof ApplicationFailure) {
  console.error(error.cause.type);
}

TemporalFailure is the union of ApplicationFailure, CancelledFailure, TerminatedFailure, TimeoutFailure, ChildWorkflowFailure, ServerFailure, ActivityFailure.

From executeWorkflow and handle.result().

Client-side validation errors ​

All TaggedErrors on the err channel, all carrying issues.

ClassTag suffixExtra properties
WorkflowValidationErrorWorkflowValidationErrorworkflowName, direction: "input" | "output", workflowId
QueryValidationErrorQueryValidationErrorqueryName, direction
SignalValidationErrorSignalValidationErrorsignalName
UpdateValidationErrorUpdateValidationErrorupdateName, direction

Worker errors ​

From @temporal-contract/worker/workflow and /activity.

ValidationError subclasses ​

These extend ApplicationFailure, are non-retryable, and carry issues. They are thrown, not returned.

ClassThrown when
WorkflowInputValidationErrorWorkflow input fails its schema
WorkflowOutputValidationErrorWorkflow return value fails its schema
ActivityInputValidationErrorActivity input fails its schema, or a middleware substitution does
ActivityOutputValidationErrorActivity return value fails its schema
QueryInputValidationErrorQuery payload fails its schema
QueryOutputValidationErrorQuery return value fails its schema
UpdateInputValidationErrorUpdate payload fails its schema
UpdateOutputValidationErrorUpdate return value fails its schema
ContractErrorDataValidationErrorA contract error's data fails its schema, or an undeclared error name is raised
ContractMisuseErrorWorkflow-sandbox code misuses the contract — see below

ValidationError itself is exported as the abstract base, for instanceof checks across all of them.

There is no SignalInputValidationError: a signal payload failing its schema is dropped and logged (log.warn), never thrown — a fire-and-forget message must not be able to kill the execution.

ContractMisuseError ​

Extends ValidationError (non-retryable ApplicationFailure), with an empty issues array — the misuse is structural, not a payload failure. Thrown when workflow-sandbox code misuses the contract surface, at one of two different points, with two different runtime consequences:

  • Binding a signal/query/update handler for an undeclared name, or using an async-validating schema where Temporal requires synchronous validation. These are caught from inside the running implementation — handleSignal/handleQuery/handleUpdate execute there, after Temporal has already invoked the workflow function. Failing terminally is the point here: a plain Error thrown from that point would be retried as a Workflow Task failure forever, leaving the execution silently Running; ContractMisuseError instead fails the execution with a clear message.
  • Reaching an activity no options cover — and, by the same mechanism, naming a workflow the contract does not declare, or an activityOptionsByName key that matches no declared activity. These checks run inside declareWorkflow itself, at module top level, before Temporal ever invokes the workflow function. A throw at that point is a Workflow Task failure regardless of the error class — nonRetryable has no effect on a failure that never reaches a FailWorkflowExecution command — so it stalls the workflow via indefinite workflow-task retry, the same way the plain Error it replaces always did. This is deliberate: see Worker surface → Activity bounds.

ActivityDefinitionNotFoundError ​

_tag: "@temporal-contract/ActivityDefinitionNotFoundError"

An activity name has no definition on the contract.

PropertyType
activityNamestring
availableDefinitionsreadonly string[]

ActivityError ​

_tag: "@temporal-contract/ActivityError" · channel: err

Any activity call failed for a reason other than one of its declared errors — retries exhausted, a timeout, an undeclared ApplicationFailure type, or a boundary validation failure. This is every activity's fallback: one with no errors map has no declared-error members to fall through, so every non-cancellation failure lands here.

PropertyType
activityNamestring
causethe unwrapped actionable failure
originalFailurethe failure exactly as caught, before the unwrap (typically Temporal's ActivityFailure wrapper) — undefined when there is no separate wrapper to retain

originalFailure exists so propagateFailure can re-raise the exact failure Temporal originally produced without changing what cause means for existing consumers that narrow on it — see Worker surface.

ActivityCancelledError ​

_tag: "@temporal-contract/ActivityCancelledError" · channel: err

A call to an activity was cancelled — declared errors map or not. A sibling of ActivityError, not a subclass, so call sites discriminate on the tag.

Swallowing this changes the workflow outcome

Cancellation rides this modeled Err(...) channel, so generic handling that folds every Err to a fallback value absorbs it — the workflow completes Completed instead of Cancelled. Re-raise it with rethrowCancellation when the workflow should honor the request. See Handle cancellation.

PropertyType
activityNamestring
causeunknown

ChildWorkflowNotFoundError ​

_tag: "@temporal-contract/ChildWorkflowNotFoundError" · channel: err

The workflow name is not on the contract passed to startChildWorkflow / executeChildWorkflow.

PropertyType
workflowNamestring
availableWorkflowsreadonly string[]

ChildWorkflowError ​

_tag: "@temporal-contract/ChildWorkflowError" · channel: err

A child workflow operation failed. cause is the unwrapped underlying failure, lifted out of Temporal's ChildWorkflowFailure wrapper.

ChildWorkflowCancelledError ​

_tag: "@temporal-contract/ChildWorkflowCancelledError" · channel: err

The child was cancelled — directly, via its parent, or via an enclosing scope. A sibling of ChildWorkflowError, so an exhaustive matcher folds the union cleanly.

PropertyType
workflowNamestring
causeunknown

WorkflowCancelledError ​

_tag: "@temporal-contract/WorkflowCancelledError" · channel: err

A typed cancellation scope was cancelled. Returned by cancellableScope (when the workflow or an ancestor cancels) and by nonCancellableScope (only when cancellation is raised from inside the scope).

A non-cancellation throw inside a scope is an unmodeled failure and rides the defect channel instead.

Error channel by operation ​

Client ​

Operationerr channel
TypedClient.createnever
startWorkflowWorkflowNotInContractError | WorkflowValidationError | WorkflowAlreadyStartedError
executeWorkflowthe above, plus WorkflowFailedError | WorkflowExecutionNotFoundError | ContractErrorUnion
signalWithStartWorkflowNotInContractError | WorkflowValidationError | SignalValidationError | WorkflowAlreadyStartedError
getHandle (sync Result)WorkflowNotInContractError
handle.queries.*QueryValidationError | WorkflowExecutionNotFoundError
handle.signals.*SignalValidationError | WorkflowExecutionNotFoundError
handle.updates.*UpdateValidationError | WorkflowExecutionNotFoundError
handle.startUpdate / update-handle result()UpdateValidationError | WorkflowExecutionNotFoundError
handle.result()ContractErrorUnion | WorkflowValidationError | WorkflowFailedError | WorkflowExecutionNotFoundError
handle.terminate/cancel/describe/fetchHistoryWorkflowExecutionNotFoundError
schedule.createWorkflowNotInContractError | WorkflowValidationError | ScheduleAlreadyExistsError
schedule handle methodsScheduleNotFoundError

Worker ​

Operationerr channel
TypedWorker.create / TypedWorker.runnever
activity call, no declared errorsActivityError | ActivityCancelledError
activity call, declared errorsContractErrorUnion | ActivityError | ActivityCancelledError
startChildWorkflowChildWorkflowError | ChildWorkflowCancelledError | ChildWorkflowNotFoundError
executeChildWorkflowsame
child handle.result()ChildWorkflowError | ChildWorkflowCancelledError
child handle.signals.*ChildWorkflowError | ChildWorkflowCancelledError
cancellableScope / nonCancellableScopeWorkflowCancelledError

An empty err channel (never) means every failure is a defect.

Next ​

Released under the MIT License.