From 28eb911a2a7e95bf5142813bbb2872c1a3f07a11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Flor=C3=AAncio?= Date: Sun, 6 Sep 2026 15:14:49 +0100 Subject: [PATCH] fix: suppress invalid task timestamps (#3434) --- .../chat/messages/message-actions.test.tsx | 15 +++ .../task/chat/messages/message-actions.tsx | 5 +- .../lib/state/slices/session/turn-actions.ts | 63 +--------- apps/web/lib/utils.test.ts | 7 ++ apps/web/lib/utils.ts | 2 + apps/web/lib/utils/strict-timestamp.ts | 66 +++++++++++ docs/plans/invalid-task-date-display/plan.md | 109 ++++++++++++++++++ ...-01-suppress-invalid-message-timestamps.md | 95 +++++++++++++++ .../task-prompt-transcript-visibility.md | 1 + .../task-prompt-transcript-visibility.md | 9 +- 10 files changed, 309 insertions(+), 63 deletions(-) create mode 100644 apps/web/lib/utils/strict-timestamp.ts create mode 100644 docs/plans/invalid-task-date-display/plan.md create mode 100644 docs/plans/invalid-task-date-display/task-01-suppress-invalid-message-timestamps.md diff --git a/apps/web/components/task/chat/messages/message-actions.test.tsx b/apps/web/components/task/chat/messages/message-actions.test.tsx index e96867583f..377252c3b1 100644 --- a/apps/web/components/task/chat/messages/message-actions.test.tsx +++ b/apps/web/components/task/chat/messages/message-actions.test.tsx @@ -98,6 +98,21 @@ describe("MessageActions timestamp tooltip", () => { expect(timeEl?.getAttribute("title")).toBe(new Date(MESSAGE_TIMESTAMP).toLocaleString()); }); + it.each(["", "not-a-date", "0", "2026-02-30T10:00:00Z"])( + "omits the timestamp affordance for invalid created_at value %j", + (createdAt) => { + const { container } = render( + + + , + ); + + expect(container.querySelector("time")).toBeNull(); + expect(container.textContent).not.toContain("Invalid Date"); + expect(screen.getByRole("button", { name: /copy message to clipboard/i })).toBeTruthy(); + }, + ); + it("omits the timestamp element entirely when showTimestamp is false", () => { const { container } = render( diff --git a/apps/web/components/task/chat/messages/message-actions.tsx b/apps/web/components/task/chat/messages/message-actions.tsx index b240bba6bc..8700cdfbcc 100644 --- a/apps/web/components/task/chat/messages/message-actions.tsx +++ b/apps/web/components/task/chat/messages/message-actions.tsx @@ -15,6 +15,7 @@ import { } from "@tabler/icons-react"; import { cn } from "@/lib/utils"; import { formatRelativeTime } from "@/lib/utils"; +import { parseStrictRfc3339Timestamp } from "@/lib/utils/strict-timestamp"; import { formatPromptDuration, messageTurnDurationSeconds } from "@/lib/prompt-history"; import { useCopyToClipboard } from "@/hooks/use-copy-to-clipboard"; import { useAppStore } from "@/components/state-provider"; @@ -247,7 +248,9 @@ function MessageTimestamp({ createdAt }: { createdAt: string }) { const { t } = useTranslation(); const usesTouchDrawer = useTouchDrawer(); const [open, setOpen] = useState(false); - const absoluteTime = new Date(createdAt).toLocaleString(); + if (parseStrictRfc3339Timestamp(createdAt) === null) return null; + const date = new Date(createdAt); + const absoluteTime = date.toLocaleString(); const timeEl = (