From 8e6cd11d9ce6b7d4376c1a8ff85cda907170eb8c Mon Sep 17 00:00:00 2001 From: Joshua King Date: Fri, 5 Jun 2026 14:34:08 -0400 Subject: [PATCH] hub: scan recorded_at via sql.NullTime in ListCameras modernc/sqlite returns a COALESCE() expression as a raw string (no column type affinity), which can't scan into *time.Time. Drop the COALESCE on the timestamp and scan the plain DATETIME column (which modernc returns as time.Time) through sql.NullTime, so a camera with no status row yet lists with a zero time instead of erroring out the whole list. Co-Authored-By: Claude Opus 4.8 --- internal/api/cameras.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/internal/api/cameras.go b/internal/api/cameras.go index 755adca..a9cead3 100644 --- a/internal/api/cameras.go +++ b/internal/api/cameras.go @@ -31,7 +31,7 @@ func ListCameras(database *db.DB) http.HandlerFunc { s.resolution, s.fps, COALESCE(s.online, 0), - COALESCE(s.recorded_at, c.created_at) + s.recorded_at FROM cameras c LEFT JOIN ( SELECT camera_id, battery_pct, video_remaining_sec, recording_state, @@ -52,15 +52,17 @@ func ListCameras(database *db.DB) http.HandlerFunc { for rows.Next() { var sl models.StatusLog var c models.Camera + var recordedAt sql.NullTime // NULL for a camera with no status yet if err := rows.Scan( &c.CameraID, &c.FriendlyName, &sl.BatteryPct, &sl.VideoRemainingSec, &sl.RecordingState, &sl.Mode, &sl.Resolution, &sl.FPS, - &sl.Online, &sl.RecordedAt, + &sl.Online, &recordedAt, ); err != nil { log.Printf("Error scanning camera row: %v", err) continue } + sl.RecordedAt = recordedAt.Time // zero time if no status statuses = append(statuses, models.NewCameraStatus(c, sl)) } if err := rows.Err(); err != nil {