diff --git a/types/defines/rpc.d.ts b/types/defines/rpc.d.ts index 1b43f0ff4b9..a9f868bebdb 100644 --- a/types/defines/rpc.d.ts +++ b/types/defines/rpc.d.ts @@ -159,6 +159,57 @@ declare namespace Rpc { > } +/** + * Error thrown across a Workers RPC boundary — for example, from a + * `DurableObjectStub`, a service binding, a `WorkerEntrypoint`, or an + * `RpcTarget`. The Workers runtime annotates tunneled exceptions with extra + * boolean hints so client code can decide whether to retry, back off, or give + * up. + * + * All properties are optional and only present when the runtime has set them; + * they are never set to `false`. + * + * @see https://developers.cloudflare.com/durable-objects/best-practices/error-handling/ + */ +interface WorkersRpcError extends Error { + /** + * `true` when the failure is transient (for example, a lost network + * connection) and the operation is safe to retry, typically with randomized + * exponential backoff. Only retry if the request is idempotent. + */ + retryable?: boolean; + + /** + * `true` when the RPC target is overloaded. Do NOT retry: additional + * requests will worsen the overload and increase the overall error rate. + */ + overloaded?: boolean; + + /** + * `true` when the exception originated on the remote side, either from user + * code running inside the RPC target or from infrastructure running on its + * behalf (for example, when a Durable Object exceeds its memory or CPU + * limits). + */ + remote?: boolean; +} + +/** + * Error thrown by a `DurableObjectStub` when a call to a remote Durable Object + * fails. Extends {@link WorkersRpcError} with Durable-Object-specific hints. + * + * @see https://developers.cloudflare.com/durable-objects/best-practices/error-handling/ + */ +interface DurableObjectError extends WorkersRpcError { + /** + * `true` when the Durable Object was reset (for example, due to a + * redeployment, an internal restart, or a storage operation that exceeded + * its timeout). The current stub is broken; create a new `DurableObjectStub` + * before issuing further requests. + */ + durableObjectReset?: boolean; +} + declare namespace Cloudflare { // Type of `env`. // diff --git a/types/generated-snapshot/experimental/index.d.ts b/types/generated-snapshot/experimental/index.d.ts index 8c14269bbcf..2df9f30df50 100755 --- a/types/generated-snapshot/experimental/index.d.ts +++ b/types/generated-snapshot/experimental/index.d.ts @@ -14196,6 +14196,53 @@ declare namespace Rpc { Exclude> >; } +/** + * Error thrown across a Workers RPC boundary — for example, from a + * `DurableObjectStub`, a service binding, a `WorkerEntrypoint`, or an + * `RpcTarget`. The Workers runtime annotates tunneled exceptions with extra + * boolean hints so client code can decide whether to retry, back off, or give + * up. + * + * All properties are optional and only present when the runtime has set them; + * they are never set to `false`. + * + * @see https://developers.cloudflare.com/durable-objects/best-practices/error-handling/ + */ +interface WorkersRpcError extends Error { + /** + * `true` when the failure is transient (for example, a lost network + * connection) and the operation is safe to retry, typically with randomized + * exponential backoff. Only retry if the request is idempotent. + */ + retryable?: boolean; + /** + * `true` when the RPC target is overloaded. Do NOT retry: additional + * requests will worsen the overload and increase the overall error rate. + */ + overloaded?: boolean; + /** + * `true` when the exception originated on the remote side, either from user + * code running inside the RPC target or from infrastructure running on its + * behalf (for example, when a Durable Object exceeds its memory or CPU + * limits). + */ + remote?: boolean; +} +/** + * Error thrown by a `DurableObjectStub` when a call to a remote Durable Object + * fails. Extends {@link WorkersRpcError} with Durable-Object-specific hints. + * + * @see https://developers.cloudflare.com/durable-objects/best-practices/error-handling/ + */ +interface DurableObjectError extends WorkersRpcError { + /** + * `true` when the Durable Object was reset (for example, due to a + * redeployment, an internal restart, or a storage operation that exceeded + * its timeout). The current stub is broken; create a new `DurableObjectStub` + * before issuing further requests. + */ + durableObjectReset?: boolean; +} declare namespace Cloudflare { // Type of `env`. // diff --git a/types/generated-snapshot/experimental/index.ts b/types/generated-snapshot/experimental/index.ts index d458fd5dd2f..89c049543be 100755 --- a/types/generated-snapshot/experimental/index.ts +++ b/types/generated-snapshot/experimental/index.ts @@ -14167,6 +14167,53 @@ export declare namespace Rpc { Exclude> >; } +/** + * Error thrown across a Workers RPC boundary — for example, from a + * `DurableObjectStub`, a service binding, a `WorkerEntrypoint`, or an + * `RpcTarget`. The Workers runtime annotates tunneled exceptions with extra + * boolean hints so client code can decide whether to retry, back off, or give + * up. + * + * All properties are optional and only present when the runtime has set them; + * they are never set to `false`. + * + * @see https://developers.cloudflare.com/durable-objects/best-practices/error-handling/ + */ +export interface WorkersRpcError extends Error { + /** + * `true` when the failure is transient (for example, a lost network + * connection) and the operation is safe to retry, typically with randomized + * exponential backoff. Only retry if the request is idempotent. + */ + retryable?: boolean; + /** + * `true` when the RPC target is overloaded. Do NOT retry: additional + * requests will worsen the overload and increase the overall error rate. + */ + overloaded?: boolean; + /** + * `true` when the exception originated on the remote side, either from user + * code running inside the RPC target or from infrastructure running on its + * behalf (for example, when a Durable Object exceeds its memory or CPU + * limits). + */ + remote?: boolean; +} +/** + * Error thrown by a `DurableObjectStub` when a call to a remote Durable Object + * fails. Extends {@link WorkersRpcError} with Durable-Object-specific hints. + * + * @see https://developers.cloudflare.com/durable-objects/best-practices/error-handling/ + */ +export interface DurableObjectError extends WorkersRpcError { + /** + * `true` when the Durable Object was reset (for example, due to a + * redeployment, an internal restart, or a storage operation that exceeded + * its timeout). The current stub is broken; create a new `DurableObjectStub` + * before issuing further requests. + */ + durableObjectReset?: boolean; +} export declare namespace Cloudflare { // Type of `env`. // diff --git a/types/generated-snapshot/latest/index.d.ts b/types/generated-snapshot/latest/index.d.ts index 29b0f1a2314..df0b2a9e053 100755 --- a/types/generated-snapshot/latest/index.d.ts +++ b/types/generated-snapshot/latest/index.d.ts @@ -13536,6 +13536,53 @@ declare namespace Rpc { Exclude> >; } +/** + * Error thrown across a Workers RPC boundary — for example, from a + * `DurableObjectStub`, a service binding, a `WorkerEntrypoint`, or an + * `RpcTarget`. The Workers runtime annotates tunneled exceptions with extra + * boolean hints so client code can decide whether to retry, back off, or give + * up. + * + * All properties are optional and only present when the runtime has set them; + * they are never set to `false`. + * + * @see https://developers.cloudflare.com/durable-objects/best-practices/error-handling/ + */ +interface WorkersRpcError extends Error { + /** + * `true` when the failure is transient (for example, a lost network + * connection) and the operation is safe to retry, typically with randomized + * exponential backoff. Only retry if the request is idempotent. + */ + retryable?: boolean; + /** + * `true` when the RPC target is overloaded. Do NOT retry: additional + * requests will worsen the overload and increase the overall error rate. + */ + overloaded?: boolean; + /** + * `true` when the exception originated on the remote side, either from user + * code running inside the RPC target or from infrastructure running on its + * behalf (for example, when a Durable Object exceeds its memory or CPU + * limits). + */ + remote?: boolean; +} +/** + * Error thrown by a `DurableObjectStub` when a call to a remote Durable Object + * fails. Extends {@link WorkersRpcError} with Durable-Object-specific hints. + * + * @see https://developers.cloudflare.com/durable-objects/best-practices/error-handling/ + */ +interface DurableObjectError extends WorkersRpcError { + /** + * `true` when the Durable Object was reset (for example, due to a + * redeployment, an internal restart, or a storage operation that exceeded + * its timeout). The current stub is broken; create a new `DurableObjectStub` + * before issuing further requests. + */ + durableObjectReset?: boolean; +} declare namespace Cloudflare { // Type of `env`. // diff --git a/types/generated-snapshot/latest/index.ts b/types/generated-snapshot/latest/index.ts index 863901436d5..826e089264a 100755 --- a/types/generated-snapshot/latest/index.ts +++ b/types/generated-snapshot/latest/index.ts @@ -13507,6 +13507,53 @@ export declare namespace Rpc { Exclude> >; } +/** + * Error thrown across a Workers RPC boundary — for example, from a + * `DurableObjectStub`, a service binding, a `WorkerEntrypoint`, or an + * `RpcTarget`. The Workers runtime annotates tunneled exceptions with extra + * boolean hints so client code can decide whether to retry, back off, or give + * up. + * + * All properties are optional and only present when the runtime has set them; + * they are never set to `false`. + * + * @see https://developers.cloudflare.com/durable-objects/best-practices/error-handling/ + */ +export interface WorkersRpcError extends Error { + /** + * `true` when the failure is transient (for example, a lost network + * connection) and the operation is safe to retry, typically with randomized + * exponential backoff. Only retry if the request is idempotent. + */ + retryable?: boolean; + /** + * `true` when the RPC target is overloaded. Do NOT retry: additional + * requests will worsen the overload and increase the overall error rate. + */ + overloaded?: boolean; + /** + * `true` when the exception originated on the remote side, either from user + * code running inside the RPC target or from infrastructure running on its + * behalf (for example, when a Durable Object exceeds its memory or CPU + * limits). + */ + remote?: boolean; +} +/** + * Error thrown by a `DurableObjectStub` when a call to a remote Durable Object + * fails. Extends {@link WorkersRpcError} with Durable-Object-specific hints. + * + * @see https://developers.cloudflare.com/durable-objects/best-practices/error-handling/ + */ +export interface DurableObjectError extends WorkersRpcError { + /** + * `true` when the Durable Object was reset (for example, due to a + * redeployment, an internal restart, or a storage operation that exceeded + * its timeout). The current stub is broken; create a new `DurableObjectStub` + * before issuing further requests. + */ + durableObjectReset?: boolean; +} export declare namespace Cloudflare { // Type of `env`. // diff --git a/types/test/types/rpc.ts b/types/test/types/rpc.ts index 07a4d0346da..cd790061462 100644 --- a/types/test/types/rpc.ts +++ b/types/test/types/rpc.ts @@ -784,6 +784,44 @@ export default >{ >; } + // Verify the shape of WorkersRpcError and DurableObjectError matches what + // the runtime stamps onto tunneled exceptions from RPC / DO stubs. + { + try { + const stub = env.RPC_OBJECT.get(env.RPC_OBJECT.newUniqueId()); + await stub.fetch('https://example.com'); + } catch (e) { + // Base RPC error: retryable / overloaded / remote apply to any + // tunneled Workers RPC exception (Fetcher, service binding, + // WorkerEntrypoint, RpcTarget, Durable Object, Workflow). + const rpcErr = e as WorkersRpcError; + expectTypeOf(rpcErr).toExtend(); + expectTypeOf(rpcErr.retryable).toEqualTypeOf(); + expectTypeOf(rpcErr.overloaded).toEqualTypeOf(); + expectTypeOf(rpcErr.remote).toEqualTypeOf(); + + // `durableObjectReset` is DO-specific and not on the base RPC error. + expectTypeOf().not.toHaveProperty( + 'durableObjectReset' + ); + + // Durable-Object-specific error adds `durableObjectReset`. + const doErr = e as DurableObjectError; + expectTypeOf(doErr).toExtend(); + expectTypeOf(doErr).toExtend(); + expectTypeOf(doErr.retryable).toEqualTypeOf(); + expectTypeOf(doErr.overloaded).toEqualTypeOf(); + expectTypeOf(doErr.remote).toEqualTypeOf(); + expectTypeOf(doErr.durableObjectReset).toEqualTypeOf< + boolean | undefined + >(); + + // Both are assignable to Error (they extend it). + const asError: Error = doErr; + expectTypeOf(asError).toExtend(); + } + } + return new Response(); }, };