fix(benchmarks): stop leaking 'latest' placeholder to postgres date cast - #6
Merged
Merged
Conversation
The /api/v1/benchmarks GET was throwing a 500 with 'Invalid time value'
on initial page load. Root cause:
useBenchmarks(model, undefined)
→ benchmarkQueryOptions(model, date ?? 'latest') // fallback marker
→ fetchBenchmarks(model, 'latest', …) // passes 'latest'!
→ GET /api/v1/benchmarks?date=latest
→ getLatestBenchmarks(sql, dbModelKeys, 'latest')
→ SQL: AND br.date <= ${'latest'}::date
→ postgres-js: new Date('latest') → NaN
→ Date.prototype.toISOString → RangeError('Invalid time value')
→ 500
The 'latest' string was only intended as a queryKey marker for "no
specific date", but it leaked through to the fetch URL. Fix:
- benchmarkQueryOptions: skip the date when it's the 'latest' sentinel,
keep it in the queryKey for cache discrimination. dateForFetch is
undefined → no `date` param in the URL → API uses the no-date
latest_benchmarks MV path.
- /api/v1/benchmarks GET: defensive ISO-date regex validation. Anything
that isn't `YYYY-MM-DD` is treated as no date. Prevents future leaks
from hitting the same 500.
Worked in upstream's data shape because the upstream defaults race-loaded
quickly, but on our small DB the empty-date initial render persisted
long enough to show the 500 to users.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
/api/v1/benchmarkswas throwing HTTP 500 withInvalid time valueon initial page load. From the container logs the user shared:```
Error fetching benchmarks: RangeError: Invalid time value
at Date1.toISOString ()
at Object.serialize (.next/server/chunks/packages_db_src_connection_ts...)
at Object.ea [as execute] (...)
```
Root cause chain:
```
useBenchmarks(model, undefined)
→ benchmarkQueryOptions(model, date ?? 'latest') // 'latest' fallback
→ fetchBenchmarks(model, 'latest', …) // leaks through!
→ GET /api/v1/benchmarks?date=latest
→ SQL: br.date <= 'latest'::date
→ postgres-js: new Date('latest') = Invalid Date
→ toISOString() → RangeError → 500
```
'latest'was meant as a queryKey-cache marker but leaked into the fetch URL. Upstream doesn't see it because their defaults race-load fast; our small DB exposes the window.Fix
benchmarkQueryOptions— keep'latest'in the queryKey (cache discrimination), but passundefinedtofetchBenchmarkswhen the marker is detected. URL omits thedateparam → API uses the no-datelatest_benchmarksMV path./api/v1/benchmarksGET — defensive ISO-date regex (YYYY-MM-DD). Anything else is treated as no date. Prevents future garbage from hitting the same 500.Test plan
pnpm typecheckclean/evaluation— the 500 in container logs should stop. Page should render the 12-row recipe table immediately.🤖 Generated with Claude Code