diff --git a/ui/src/components/IssueChatThread.test.tsx b/ui/src/components/IssueChatThread.test.tsx
index 82268181708..cfccdd5d7ad 100644
--- a/ui/src/components/IssueChatThread.test.tsx
+++ b/ui/src/components/IssueChatThread.test.tsx
@@ -3276,6 +3276,57 @@ describe("IssueChatThread", () => {
act(() => root.unmount());
});
+ it("settles a restored submission only once through StrictMode effect replay", () => {
+ const key = "strict-restored-submission";
+ const attemptId = "aaf8228f-0be7-45ae-a104-6fbe0af6f1d3";
+ const submitted = "One text-only save interrupted by reload.";
+ const nextDraft = "A newer draft written while delivery was pending.";
+ localStorage.setItem(key, `${submitted}\n\n${nextDraft}`);
+ localStorage.setItem(`${key}:submission:v1`, JSON.stringify({
+ version: 1,
+ draftKey: key,
+ attemptId,
+ reviewed: false,
+ nextDraftOffset: submitted.length + 2,
+ submittedAttachmentIds: [],
+ }));
+ const root = createRoot(container);
+ try {
+ act(() => root.render(
+
+
+ {}}
+ draftKey={key}
+ enableLiveTranscriptPolling={false}
+ />
+
+ ,
+ ));
+ expect(container.querySelector(
+ 'textarea[aria-label="Issue chat editor"]',
+ )?.value).toBe(nextDraft);
+ expect(localStorage.getItem(key)).toBe(nextDraft);
+ expect(localStorage.getItem(`${key}:submission:v1`)).toBeNull();
+ expect(container.textContent).not.toContain("We couldn’t confirm");
+ } finally {
+ act(() => root.unmount());
+ }
+ expect(localStorage.getItem(key)).toBe(nextDraft);
+ });
+
it("stores and restores the composer draft per issue key", () => {
vi.useFakeTimers();
const root = createRoot(container);
diff --git a/ui/src/components/IssueChatThread.tsx b/ui/src/components/IssueChatThread.tsx
index cd1c4d5b0e4..5d8d2412b53 100644
--- a/ui/src/components/IssueChatThread.tsx
+++ b/ui/src/components/IssueChatThread.tsx
@@ -4824,7 +4824,7 @@ const IssueChatComposer = forwardRef<
if (!uncertainSubmission || !confirmedSubmissionIds.has(uncertainSubmission.attemptId)) return;
const nextDraft = uncertainSubmission.nextDraftOffset === undefined
? "" : bodyRef.current.slice(uncertainSubmission.nextDraftOffset);
- if (draftKey) settleDraftSubmission(draftKey, uncertainSubmission.attemptId, nextDraft);
+ if (draftKey && !settleDraftSubmission(draftKey, uncertainSubmission.attemptId, nextDraft)) return;
setUncertainSubmission(null);
setBody(nextDraft);
bodyRef.current = nextDraft;