From d8cc32e2e7b9af0b4fd4c69d6d24f046dc926b4d Mon Sep 17 00:00:00 2001 From: AI Assistant Date: Fri, 13 Mar 2026 19:40:30 +0900 Subject: [PATCH] Fix Gemini candidate cap causing search 500s --- TODO.md | 11 +++++++++++ backend/services/cse_test.go | 6 ++++++ backend/services/ranker.go | 2 +- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/TODO.md b/TODO.md index 5c5186a..52bf70a 100644 --- a/TODO.md +++ b/TODO.md @@ -117,6 +117,17 @@ - new service layer file: `backend/services/ranker.go` - handler is now thinner and less coupled to search internals +## Current Session Update (2026-03-13, 500 Fix) +- A server-side `request failed (500)` regression was found after the ranker split. +- Root cause: + - Gemini candidate cap logic returned `12` even when only `9` ranked candidates existed + - Gemini batch slicing then attempted to read beyond the available slice bounds +- Fix applied: + - `GeminiCandidateLimit` now never exceeds the real candidate count for totals up to 12 + - Gemini evaluation now stays within valid ranked slice bounds +- Effect: + - avoids backend 500 during the Gemini Vision evaluation stage for mid-sized result sets + ## Local Self-Test Workflow - Primary command: - `bash scripts/selftest.sh` diff --git a/backend/services/cse_test.go b/backend/services/cse_test.go index 185cd77..1320297 100644 --- a/backend/services/cse_test.go +++ b/backend/services/cse_test.go @@ -63,3 +63,9 @@ func TestIsRenderableArtgridResultAcceptsArtlistCanonical(t *testing.T) { t.Fatal("expected artlist canonical clip URL to be accepted for Artgrid collector") } } + +func TestGeminiCandidateLimitNeverExceedsCandidates(t *testing.T) { + if got := GeminiCandidateLimit(9); got != 9 { + t.Fatalf("expected Gemini limit to stay within candidate count, got %d", got) + } +} diff --git a/backend/services/ranker.go b/backend/services/ranker.go index ee5de4c..b8dd79d 100644 --- a/backend/services/ranker.go +++ b/backend/services/ranker.go @@ -81,7 +81,7 @@ func RankSearchResults(query string, results []SearchResult) []SearchResult { func GeminiCandidateLimit(total int) int { switch { - case total <= 8: + case total <= 12: return total case total <= 16: return 12