Bug: Stats() scans database columns into wrong struct fields #4

Closed
opened 2026-02-09 00:56:08 +01:00 by clawbot · 0 comments
Collaborator

Bug

In internal/imgcache/cache.go, the Stats() method scans SQL columns into mismatched struct fields:

err := c.db.QueryRowContext(ctx, `
    SELECT hit_count, miss_count, upstream_fetch_count, upstream_fetch_bytes, transform_count
    FROM cache_stats WHERE id = 1
`).Scan(&stats.HitCount, &stats.MissCount, &stats.TotalItems, &stats.TotalSizeBytes, &stats.HitRate)

The scan maps:

  • upstream_fetch_countTotalItems (wrong - this is fetch count, not item count)
  • upstream_fetch_bytesTotalSizeBytes (coincidentally reasonable but semantically wrong)
  • transform_countHitRate (completely wrong - scanning an INTEGER into a float64 field that should be a ratio)

The subsequent queries then overwrite TotalItems and TotalSizeBytes with correct values, but HitRate from the first scan is an integer (transform_count) not a ratio.

Then HitRate is recalculated correctly only if HitCount+MissCount > 0, but if they're both 0 (fresh DB), HitRate retains the garbage value from the transform_count scan.

Impact

The /metrics or any stats endpoint returns incorrect data. The HitRate field contains transform_count (an integer) instead of a 0.0-1.0 ratio.

Fix

Scan into local variables matching the actual columns, or restructure the query to only fetch hit_count and miss_count from cache_stats, then compute derived stats separately.

## Bug In `internal/imgcache/cache.go`, the `Stats()` method scans SQL columns into mismatched struct fields: ```go err := c.db.QueryRowContext(ctx, ` SELECT hit_count, miss_count, upstream_fetch_count, upstream_fetch_bytes, transform_count FROM cache_stats WHERE id = 1 `).Scan(&stats.HitCount, &stats.MissCount, &stats.TotalItems, &stats.TotalSizeBytes, &stats.HitRate) ``` The scan maps: - `upstream_fetch_count` → `TotalItems` (wrong - this is fetch count, not item count) - `upstream_fetch_bytes` → `TotalSizeBytes` (coincidentally reasonable but semantically wrong) - `transform_count` → `HitRate` (completely wrong - scanning an INTEGER into a float64 field that should be a ratio) The subsequent queries then overwrite `TotalItems` and `TotalSizeBytes` with correct values, but `HitRate` from the first scan is an integer (transform_count) not a ratio. Then `HitRate` is recalculated correctly only if `HitCount+MissCount > 0`, but if they're both 0 (fresh DB), `HitRate` retains the garbage value from the transform_count scan. ## Impact The `/metrics` or any stats endpoint returns incorrect data. The `HitRate` field contains transform_count (an integer) instead of a 0.0-1.0 ratio. ## Fix Scan into local variables matching the actual columns, or restructure the query to only fetch `hit_count` and `miss_count` from `cache_stats`, then compute derived stats separately.
clawbot self-assigned this 2026-02-09 00:56:08 +01:00
sneak closed this issue 2026-02-09 01:31:19 +01:00
Sign in to join this conversation.
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: sneak/pixa#4
No description provided.