Repository navigation
Description
What would you like?
When a checkpoint response arrives without a CheckpointToken, the SDK should treat it as a signal that the service will accept no further checkpoints from this invocation. The SDK should stop issuing checkpoints and end the invocation cleanly with Status: PENDING.
Why PENDING and not FAILED or a thrown error:
- A missing token does not mean the execution is finished. It means this invocation cannot make further progress. The invocation result must not claim the execution finished.
- A thrown error is an invocation failure. Lambda retries it, but the retry has no valid token and can do nothing useful. It also puts an error in customer logs for a condition the SDK understood.
- PENDING is already what the SDK returns for every suspend (wait, scheduled retry, pending callback). This is a suspend: the invocation is done for now and the execution continues later.
Current behavior
The checkpoint manager ignores a missing token (src/utils/checkpoint/checkpoint-manager.ts):
if (response.CheckpointToken) {
this.currentTaskToken = response.CheckpointToken;
}So the SDK keeps the consumed token and sends it on the next checkpoint. The service rejects that call with InvalidParameterValueException: Invalid checkpoint token. With the fix for #917 in place, that is classified as an invocation error and the handler throws. So the invocation ends with a Lambda error instead of a clean PENDING. Without the fix for #917, it fails the execution.
Possible Implementation
- Add
TerminationReason.EXECUTION_SUSPENDED_BY_SERVICE(name open) and classify it"suspend"inTERMINATION_CLASS.withDurableExecutionthen returns{ Status: PENDING }through the existing suspend path with no further change. - In
CheckpointManager, when a checkpoint response has noCheckpointToken, callterminationManager.terminate({ reason: ... })and stop draining the checkpoint queue. There is no token to send, so any further checkpoint is guaranteed to fail. - In-flight operations in the invocation are abandoned, not checkpointed. On the next invocation they replay. This is correct for AT_LEAST_ONCE steps. AT_MOST_ONCE steps whose START landed in the last accepted checkpoint will not run again, which is the defined semantics of AT_MOST_ONCE.
- Unit test: a checkpoint response without
CheckpointTokenproducesStatus: PENDING, no further checkpoint calls, and no thrown error. - Testing SDK: the local checkpoint server needs a way to omit the token on a chosen checkpoint so customers can test their handlers against this path.
Is this a breaking change?
No. The SDK's response set is unchanged; a new internal termination reason is added.
Additional Context
- Prerequisite: [Bug]: Invalid checkpoint token misclassified as execution failure (message case mismatch) #917 (message-case bug in stale-token classification). That fix is the fallback path whenever the missing token is not detected, so it should land first.
- Sibling issues in the Python and Java SDKs are linked in a comment below.
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsIn progress
Activity
yaythomas commentedon Sep 12, 2026
Sibling issues (same feature, one per SDK):
feat(testing): pause and resume a running execution
feat(testing): mark pause/resume experimental; not implemented in clo…
feat(examples): add local-only pause/resume example
fix(sdk): answer PENDING when the token is withdrawn after the handle…
fix(sdk): decide the invocation's answer in one place
chore: bump SDK to 2.5.0 and testing SDK to 1.2.0 (#933)