fix: knowledge/recent returned empty items — timestamptz couldn't scan into string
Some checks failed
ci / build-test (push) Has been cancelled
ci / docker-build (push) Has been cancelled

Verified live immediately after deploying: the endpoint returned 200 with
correct-looking stats (total=56, agent_authored=2) but items=[] always,
regardless of limit/source. Root cause: pgx v5 can't scan a timestamptz
column directly into a Go string — Scan() errored on every single row, and
that error was silently swallowed by a bare `continue`, so every row was
dropped with no trace in the logs. Fixed by casting updated_at::text in the
SQL (matching how every other handler in this codebase already returns
timestamps) and logging scan failures instead of swallowing them, so this
class of bug can't hide silently again.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-10 19:26:48 +02:00
parent ec41c0b828
commit 40999b0b40

View File

@@ -3,6 +3,7 @@ package httpapi
import (
"context"
"encoding/json"
"log/slog"
"net/http"
"strconv"
@@ -36,8 +37,13 @@ func (s *Server) serveRecentKnowledge(w http.ResponseWriter, req *http.Request)
AgentAuthored bool `json:"agent_authored"`
}
// updated_at is cast to text in SQL — pgx v5 can't scan a timestamptz
// directly into a Go string (needs time.Time or an explicit cast), and
// that scan error was being silently swallowed below (every row skipped,
// endpoint returned 200 with an empty list and correct-looking stats
// since the stats query doesn't scan any timestamp column — found live).
rows, err := s.pool.Query(ctx, `
SELECT e.slug, ke.title, e.type, COALESCE(ke.source,''), ke.tags, ke.updated_at
SELECT e.slug, ke.title, e.type, COALESCE(ke.source,''), ke.tags, ke.updated_at::text
FROM knowledge_entities ke
JOIN entities e ON e.id = ke.entity_id
WHERE ($1 = '' OR ke.source = $1)
@@ -53,6 +59,7 @@ func (s *Server) serveRecentKnowledge(w http.ResponseWriter, req *http.Request)
var it item
var src string
if err := rows.Scan(&it.Slug, &it.Title, &it.Kind, &src, &it.Tags, &it.UpdatedAt); err != nil {
slog.Error("httpapi: knowledge/recent row scan failed", "error", err)
continue
}
it.Source = src