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_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.
## 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
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Bug
In
internal/imgcache/cache.go, theStats()method scans SQL columns into mismatched struct fields: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
TotalItemsandTotalSizeByteswith correct values, butHitRatefrom the first scan is an integer (transform_count) not a ratio.Then
HitRateis recalculated correctly only ifHitCount+MissCount > 0, but if they're both 0 (fresh DB),HitRateretains the garbage value from the transform_count scan.Impact
The
/metricsor any stats endpoint returns incorrect data. TheHitRatefield 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_countandmiss_countfromcache_stats, then compute derived stats separately.