Skip to content

Commit f52c84b

Browse files
PfisterFactorclaude
andcommitted
feat: add metadata field to TerminalError class
Add a `metadata` field (Record<string, string>) to the TerminalError class, enabling propagation of key-value metadata through the Restate protocol (requires service protocol v6+). Changes: - TerminalError constructor now accepts an optional `metadata` option - metadata is converted to WasmFailureMetadata format ({key, value}[]) when sending to the VM via propose_run_completion_failure and sys_write_output_failure - metadata is deserialized back to Record<string, string> when receiving Failure completions from the VM Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 5f6564d commit f52c84b

File tree

3 files changed

+21
-2
lines changed

3 files changed

+21
-2
lines changed

packages/libs/restate-sdk/src/context_impl.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,9 @@ export class ContextImpl implements ObjectContext, WorkflowContext {
467467
this.coreVm.propose_run_completion_failure(handle, {
468468
code: err.code,
469469
message: err.message,
470-
metadata: [],
470+
metadata: Object.entries(err.metadata ?? {}).map(
471+
([key, value]) => ({ key, value })
472+
),
471473
});
472474
} else if (err instanceof RetryableError) {
473475
const maxRetryDuration =
@@ -1023,9 +1025,17 @@ function SuccessWithSerde<T>(
10231025

10241026
const Failure: Completer = (value, prom) => {
10251027
if (typeof value === "object" && "Failure" in value) {
1028+
const metadata = (value.Failure.metadata ?? []).reduce(
1029+
(acc: Record<string, string>, { key, value: v }: { key: string; value: string }) => {
1030+
acc[key] = v;
1031+
return acc;
1032+
},
1033+
{} as Record<string, string>
1034+
);
10261035
prom.reject(
10271036
new TerminalError(value.Failure.message, {
10281037
errorCode: value.Failure.code,
1038+
metadata,
10291039
})
10301040
);
10311041
return Promise.resolve(true);

packages/libs/restate-sdk/src/endpoint/handlers/generic.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,9 @@ export class GenericHandler implements RestateHandler {
480480
coreVm.sys_write_output_failure({
481481
code: error.code,
482482
message: error.message,
483-
metadata: [],
483+
metadata: Object.entries(error.metadata ?? {}).map(
484+
([key, value]) => ({ key, value })
485+
),
484486
});
485487
coreVm.sys_end();
486488
return;

packages/libs/restate-sdk/src/types/errors.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ export class RestateError extends Error {
9292
*/
9393
export class TerminalError extends RestateError {
9494
public override name = "TerminalError";
95+
public readonly metadata: Record<string, string>;
9596

9697
constructor(
9798
message: string,
@@ -104,9 +105,15 @@ export class TerminalError extends RestateError {
104105
* @deprecated YOU MUST NOT USE THIS FIELD, AS IT WON'T BE RECORDED AND CAN LEAD TO NON-DETERMINISM! From the next SDK version, the constructor won't accept this field anymore.
105106
*/
106107
cause?: any;
108+
/**
109+
* Metadata key-value pairs to attach to the terminal error.
110+
* These are propagated through the Restate protocol (requires service protocol v6+).
111+
*/
112+
metadata?: Record<string, string>;
107113
}
108114
) {
109115
super(message, options);
116+
this.metadata = options?.metadata ?? {};
110117
}
111118
}
112119

0 commit comments

Comments
 (0)