Skip to content

Fix null createdAt crash in Feedback vote results (Gen2 trigger regression)#1680

Merged
HugoGresse merged 3 commits into
mainfrom
fix/vote-aggregation-null-timestamp
Jun 15, 2026
Merged

Fix null createdAt crash in Feedback vote results (Gen2 trigger regression)#1680
HugoGresse merged 3 commits into
mainfrom
fix/vote-aggregation-null-timestamp

Conversation

@HugoGresse

Copy link
Copy Markdown
Owner

What

Fixes TypeError: can't access property "toDate", h.createdAt is null crashing the Feedback app's vote-results view.

Why

Commit e314b38 ("API (wip)", #1664) migrated the vote-aggregation Firestore triggers from Gen1 (functions.firestore.document().onCreate) to Gen2 (onDocumentCreated/onDocumentUpdated).

Gen2 (Eventarc) surfaces the intermediate write a serverTimestamp() makes — the create event fires before the sentinel resolves, so createdAt/updatedAt arrive as null. Gen1 hid that. The aggregation copied the null into the sessionVotes doc, and the Feedback app then crashed on the unguarded value2.createdAt.toDate() in getVoteResultSelectorSelector.js.

Frontend feedback code was unchanged for 6 months — confirms the regression is server-side.

Changes

  • functions/src/triggers/aggregateVotes.tsnormalizeVoteTimestamps() falls back to the snapshot's server-assigned createTime/updateTime when the field is null, so new aggregated docs never store a null timestamp.
  • src/feedback/talk/core/getVoteResultSelectorSelector.js — optional-chained .toDate() + skip entries with no usable date, so docs already corrupted in prod no longer crash the whole results view.

Reviewer notes

  • Existing corrupted sessionVotes docs stay corrupted in Firestore; the frontend guard hides the crash. A re-aggregation/migration script would be needed to repair existing data.
  • No unit test yet for the null-timestamp fallback (normalizeVoteTimestamps is not exported). Can add one if wanted.
  • Verified: tsc --noEmit clean, aggregateVotes.spec.ts 10/10 pass.

🤖 Generated with Claude Code

…migration

The Gen1->Gen2 Firestore trigger migration (#1664) made the vote
aggregation fire before serverTimestamp() resolves, writing null
createdAt/updatedAt into aggregated sessionVotes docs. The Feedback app
then crashed on `value2.createdAt.toDate()` with
"TypeError: can't access property toDate, h.createdAt is null".

- aggregateVotes.ts: normalizeVoteTimestamps() falls back to the
  snapshot's server-assigned createTime/updateTime when the field is
  null, so new aggregated docs never store a null timestamp.
- getVoteResultSelectorSelector.js: guard the .toDate() calls and skip
  entries with no usable date, so already-corrupted prod docs no longer
  crash the whole results view.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 15, 2026 17:09

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a production crash in the Feedback vote-results view caused by Gen2 Firestore trigger behavior exposing intermediate serverTimestamp() writes where createdAt/updatedAt can be null.

Changes:

  • Server-side: normalize vote timestamps in Gen2 triggers by falling back to Firestore snapshot createTime/updateTime when createdAt/updatedAt are null.
  • Client-side: guard .toDate() calls with optional chaining and skip corrupted entries so the results view doesn’t crash on already-bad data.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
functions/src/triggers/aggregateVotes.ts Adds timestamp normalization to avoid writing null timestamps into aggregated sessionVotes docs under Gen2 triggers.
src/feedback/talk/core/getVoteResultSelectorSelector.js Prevents UI crash by safely converting timestamps and ignoring entries without usable dates.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread functions/src/triggers/aggregateVotes.ts
Export the helper and cover the null/undefined createdAt/updatedAt
fallback to createTime/updateTime, plus the untouched-when-set case.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jun 15, 2026

Copy link
Copy Markdown

Visit the preview URL for this PR (updated for commit 70938ba):

https://open-feedback-42--pr1680-fix-vote-aggregation-jjeqhh69.web.app

(expires Mon, 22 Jun 2026 17:29:51 GMT)

🔥 via Firebase Hosting GitHub Action 🌎

Sign: 08b588459ed3335bea4061fbe93b8b77635ad43a

@cypress

cypress Bot commented Jun 15, 2026

Copy link
Copy Markdown

open-feedback    Run #3069

Run Properties:  status check passed Passed #3069  •  git commit 303b12f4bc: Fix null createdAt crash in Feedback vote results (Gen2 trigger regression) (#16...
Project open-feedback
Branch Review main
Run status status check passed Passed #3069
Run duration 02m 42s
Commit git commit 303b12f4bc: Fix null createdAt crash in Feedback vote results (Gen2 trigger regression) (#16...
Committer Hugo Gresse
View all properties for this run ↗︎

Test results
Tests that failed  Failures 0
Tests that were flaky  Flaky 1
Tests that did not run due to a developer annotating a test with .skip  Pending 0
Tests that did not run due to a failure in a mocha hook  Skipped 0
Tests that passed  Passing 14
View all changes introduced in this branch ↗︎

editVoteRangeOpenTime selected the day cell via button[tabindex=-1],
but MUI assigns today's cell tabindex=0. The test picks day 15, so it
failed on the 15th of every month. Match the day cell by exact text and
enabled state instead, removing the date dependency.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@HugoGresse HugoGresse merged commit 303b12f into main Jun 15, 2026
10 checks passed
@HugoGresse HugoGresse deleted the fix/vote-aggregation-null-timestamp branch June 15, 2026 17:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants