Skip to content

Transient Retry

client.commit.apply(...) and OperationBuilder.commit(...) assign one UUID submissionId to the logical submission and derive a stable eventRequestId for each zero-based chunk ordinal. A timeout, dropped connection, or server 5xx retries the same request identity. If the original request landed, the backend returns its immutable receipt instead of applying it again.

Auto-retry applies whenever retry is enabled, the attempt budget remains, and the failure is a transient stream failure — regardless of chunk ordinal, operation count, operation kind, or whether streamId was supplied by the caller.

A successful call returns an OperationSubmitResult — the aggregate write result with the ordered exact receipts nested under receipts, one per chunk.

Pass submissionId when your application needs to record the logical identity before calling the SDK. Otherwise the SDK mints it before the first request. streamId remains observation-only and is preserved across retries; it is not the idempotency key.

Pass retry: false to disable automatic retry:

await client.commit.apply(org, repo, message, operations, { retry: false })

Pass a RetryPolicyOptions value to override defaults:

await client.commit.apply(org, repo, message, operations, {
retry: {
maxAttempts: 4,
baseDelayMs: 100,
maxDelayMs: 1000,
},
})

OperationBuilder.commit(...) accepts the same retry option.

The SDK throws PartialStreamSubmissionError when a chunk remains ambiguous after retry, or when a later chunk is definitely rejected after earlier receipts were acknowledged. The error carries completedReceipts, submissionId, chunkOrdinal, eventRequestId, and pendingOutcome.

acknowledgedOperationCount preserves the size of the acknowledged prefix, and lastAcknowledgedRepoSeq preserves its latest event sequence when one exists. These are progress diagnostics, not evidence about the pending append. attemptedAppendOutcome is the compatibility discriminator: "not_applied" maps to pendingOutcome: "absent"; "unknown" maps to pendingOutcome: "unknown".

For pendingOutcome: "unknown", recover with:

const receipt = await client.commit.getReceipt(org, repo, error.eventRequestId)

Opaque NOT_FOUND means no visible receipt exists; only then may the identical chunk be retried with the same identity. A returned receipt is the outcome. For pendingOutcome: "absent", the pending request was definitely rejected, while completedReceipts still records earlier committed chunks.

After OperationBuilder.commit(...) throws PartialStreamSubmissionError, that builder is sealed: later mutation or commit calls fail before transport. After any outcome-unknown append has stopped, reconcile from a later verified checkpoint and create a new plan and builder.

Definite first-request rejections propagate as WarmHubError with the original kind and code. If every accepted physical operation is rejected, the high-level call throws AllStreamOperationsFailedError; its receipts field contains the exact no_event receipts and its operations field is their flattened operation sequence. Mixed successful and failed envelopes return normally for caller inspection. A low-level client.stream.append(...) returns a StreamAppendResult object; the receipt is nested under its receipt property, alongside per-operation results and optional top-level metadata — including all-failed and no-op outcomes.

When you catch PartialStreamSubmissionError, preserve completedReceipts, acknowledgedOperationCount, and lastAcknowledgedRepoSeq, then use eventRequestId for receipt lookup when the outcome is unknown. Never mint a replacement identity for an ambiguous retry. When you catch AllStreamOperationsFailedError, inspect its exact receipts and flattened operations before correcting the rejected inputs.