Repository navigation
Description
Before submitting
- I searched existing issues and did not find a duplicate.
- I included enough detail to reproduce or investigate the problem.
Area
apps/server
Steps to reproduce
- Snooze a thread with Next week.
- Let its session fail after the snooze. In my case two Claude threads ran turns that failed at once with "Claude usage limit reached". The thread comes back as Failed, as intended: a failure newer than the snooze raises its hand.
- Snooze it again with Next week.
Expected behavior
The thread leaves the inbox until the new wake time.
Actual behavior
The command is accepted, but the thread stays in the inbox as Failed. Snoozing again with the same option does the same every time. I did it six times in 12 minutes on one thread. It looks like the snooze hangs or does nothing, with no toast.
Cause
A re-snooze to the same wake time is treated as a duplicate, and the original snoozedAt is kept:
- server:
apps/server/src/orchestration/decider.ts,thread.snooze, theexistingSnoozedAtbranch - client optimistic twin:
packages/client-runtime/src/state/threadCommands.ts,snoozedAt: thread.snoozedUntil === input.snoozedUntil ? (thread.snoozedAt ?? now) : now
The raised-hand check in threadRaisedHandWhileSnoozed (packages/client-runtime/src/state/threadSettled.ts) compares session.updatedAt and latestTurn.completedAt against that stale snoozedAt. The failure is still newer, so the thread never classifies as snoozed again until the user picks a different wake time. Presets such as Tomorrow and Next week resolve to fixed clock times, so repeating the same option is the normal case.
Suggested fix
Remove the same-wake-time branch in both places, so an explicit snooze always stamps snoozedAt now. Re-snoozing means "I saw it, not now", so it should reset the raised-hand baseline. Real retries are already deduplicated by commandId receipts, and a double-click only moves the stamp by milliseconds. This is a net deletion. Update the existing decider.snoozed.test.ts case ("re-emits idempotently for a duplicate snooze to the same wake time") to assert a fresh snoozedAt. I can open the PR.
Impact
Minor bug or occasional failure
Version or commit
t3@0.0.43-nightly.20260929.2428 (main d2c9281). The code is unchanged on current main.
Environment
Linux host running t3 serve as a service, macOS desktop client connected remotely, Claude provider. Not specific to remote connections: the server accepted every command.
Logs or stack traces
# orchestration_events for one thread (UTC)
17:30:47.626 thread.snoozed client snoozedUntil 2026-10-05T07:00Z snoozedAt 17:30:47.626
17:45:45.170 thread.session-set provider status error "Claude usage limit reached…"
17:58:01.695 thread.session-set provider status error "Claude usage limit reached…" <- raises hand
17:58:19.209 thread.snoozed client snoozedUntil 2026-10-05T07:00Z snoozedAt 17:30:47.626 <- stale
17:58:33.557 thread.snoozed client …same…
17:58:52.528 thread.snoozed client …same…
18:03:21.077 thread.snoozed client …same…
18:04:53.764 thread.snoozed client …same…
18:10:21.969 thread.snoozed client …same…
# all receipts: accepted; projection_threads.snoozed_at stays 17:30:47.626
A second thread shows the same pattern (snoozed 17:30:40, error at 18:05:45, re-snoozes at 18:08 and 18:10 all keep 17:30:40).
Screenshots, recordings, or supporting files
Both threads after six "Next week" re-snoozes between 17:58 and 18:10. Every command was accepted, and both rows are still in the inbox as Failed:
Workaround
Snooze with a different option, such as Tomorrow or 3 hours. That stamps a fresh snoozedAt and the snooze holds.
Related
- [Bug]: completed work wakes snoozed threads and breaks subsequent snoozing #6368 reports "re-snoozing may then not put it in the Snoozed shelf" without a cause. This is likely that half. The other half, completed work waking a snoozed thread, is a wake-policy question and is not addressed here. Closed fix(threads): keep snoozed threads hidden when work finishes #7179 did not touch this branch.
- [Bug]: A thread stopped by a usage limit is labelled Failed, indistinguishable from a crash #10545: usage-limit stops read as Failed. That is orthogonal; it is what woke these threads here.
Activity
[-][Bug]: Snoozing a woken thread again with the same option is accepted but does nothing[/-][+][Bug]: A thread that woke from snooze cannot be snoozed again to the same wake time[/+]vitalyiegorov commentedon Sep 29, 2026
PR opened: #14299. It removes the same-wake-time branch in the decider and its optimistic twin, so every snooze stamps a fresh
snoozedAt. The existing duplicate-snooze test now asserts the fix and fails without it.juliusmarminge commentedon Sep 29, 2026
Triage
Confirmed on
mainatd2c9281b81. A re-snooze to the same wake time keeps the originalsnoozedAt, so a failure or completion that is still newer than that stamp keeps the thread in the inbox.thread.snoozeinapps/server/src/orchestration/decider.tstreats an unchangedsnoozedUntilas a duplicate and re-emits the storedsnoozedAtandupdatedAt. The optimistic twin inpackages/client-runtime/src/state/threadCommands.tsdoes the same (snoozedAt: thread.snoozedUntil === input.snoozedUntil ? (thread.snoozedAt ?? now) : now). The projector copiespayload.snoozedAtthrough, so the row never moves. The reported events match that: six acceptedthread.snoozedevents, all still stamped17:30:47.626.Raising a hand does not clear the snooze fields.
threadRaisedHandWhileSnoozedonly stops the thread from classifying as snoozed when a session error'supdatedAt, or a completed turn'scompletedAt, is newer thansnoozedAt.snoozedUntilstays set, so the next click of the same preset compares equal and the old stamp wins. The comment next to that check already says a snooze of an already-failed thread means "I saw it, not now". This branch makes that false whenever the wake time does not change.Calendar presets are stable.
resolveSnoozePresetspins This evening, Tomorrow, and Next week to a local clock time, so repeating Next week is the samesnoozedUntil(here2026-10-05T07:00Z). In 1 hour and In 3 hours mint a new instant on every click, which is why a different option hides the thread.This is not a duplicate of #6368. That issue's first half, completed work waking a snoozed thread, is the current raised-hand policy and is untouched here. Its "re-snooze may not land in Snoozed" half is this bug, but #6368 has no cause and also asks for the wake policy to change. Closed #7179 only removed the completion comparison in
threadRaisedHandWhileSnoozedand never merged; it did not touch this branch. #10545 is why a usage-limit stop reads as Failed. That is what raised the hand, not why the re-snooze was ignored.The same-wake branch is not the retry guard.
OrchestrationEnginereturns the existing receipt before the decider runs, so a replayedcommandIdnever reaches this code. A double-click is a new command and only moves the stamp by milliseconds. The raised-hand checks are strict>, so that is enough.Always stamp
snoozedAtandupdatedAtfrom now, in the decider and the optimistic twin. The decider test "re-emits idempotently for a duplicate snooze to the same wake time" asserts the bug and has to flip. Open PR #14299 does that.Workaround until it ships: pick a different wake time.
vitalyiegorov commentedon Oct 5, 2026
Still happens on V2:
thread.snoozeinOrchestrator.tskeeps the originalsnoozedAtfor a re-snooze to the same wake time. Fix rebuilt on V2 main in #15881.fix(server): re-snoozing a woken thread to the same wake time hides i…