Task.define() creates a TaskDefinition — the core building block of @durable-effect/task. You provide Effect Schemas for state and events, then write handlers that run inside a TaskContext.
Signature
| Parameter | Description |
|---|---|
S | State type |
E | Event type |
EErr | Error type from onEvent |
AErr | Error type from onAlarm |
R | Effect service requirements shared across handlers |
OErr | Error type from onError (default never) |
GErr | Error type from onClientGetState (default never) |
Config fields
Effect Schema for the task’s persisted state. Must be a pure schema — no service dependencies for encoding or decoding.
Effect Schema for incoming events. Same purity requirement as
state.Called when an event is sent to this task via
send(). Use ctx to read and write state, schedule alarms, or terminate the task. The handler runs inside the Effect runtime backed by Durable Object storage.Called when a previously scheduled alarm fires. Cloudflare invokes this automatically when the alarm time arrives. Use
ctx.scheduleIn() or ctx.scheduleAt() inside this handler to re-schedule.Optional. Called when
onEvent or onAlarm fails. Receives the full TaskContext<S> and the raw error value. Use it to save recovery state, log failures, or perform cleanup.If omitted, unhandled errors propagate as TaskExecutionError.Optional. Intercepts external
getState() calls before the state is returned to the client. The hook receives the full TaskContext<S> and the raw persisted state, and must return S | null.This hook does not affect ctx.recall() inside your handlers — it only runs when an external caller invokes getState().Common uses: redact sensitive fields, compute derived values, or enrich state from external services.Return type
Task.define() returns a TaskDefinition<S, E, EErr, AErr, R, OErr, GErr>:
createTasks(), or wrap it with withServices() first if your handlers depend on Effect services.
Purity constraint
State and event schemas must satisfyPureSchema<T>, which requires that encoding and decoding have no service dependencies (DecodingServices and EncodingServices are both never):
Schema.Struct, Schema.Number, Schema.String, Schema.Literal, and similar built-in schemas are always pure.
withServices(definition, layer)
If your handlers require Effect services (databases, HTTP clients, etc.), use withServices() to provide a Layer and eliminate the R type parameter before passing to createTasks():
withServices() wraps each handler with Effect.provide(handler, layer), returning a new TaskDefinition with R set to never. The state and event schemas are unchanged.
Error behavior
WithoutonError, any exception thrown (or Effect.fail) inside onEvent or onAlarm surfaces as a TaskExecutionError with the original error as cause. The onError handler receives the typed error union EErr | AErr and can use the full TaskContext<S> to react:
