Surfaced during review of #440 (pre-existing; out of scope for that PR).
internal/infrastructure/depsdev/advisory.go — FetchAdvisoriesBatch returns map[string]*AdvisoryDetail with no error return. On a per-advisory fetch failure it logs at DEBUG and drops the entry:
detail, err := c.FetchAdvisory(ctx, advisoryID)
if err != nil {
slog.Debug("failed to fetch advisory detail", "id", advisoryID, "error", err)
return "", nil, false // dropped — caller cannot distinguish "no advisory" from "fetch failed"
}
The completion log is also DEBUG, so a partial result (e.g. severity data missing due to a transient 5xx) is indistinguishable downstream from "package has no advisories". This can understate vulnerability severity silently.
Fix options
- Return a failed-ID set (or error) alongside the map so callers can surface/retry, or
- At minimum, log failures at WARN with a count after the batch.
Acceptance
- Advisory fetch failures are observable to callers or surfaced at WARN with counts (not silently dropped at DEBUG).
Surfaced during review of #440 (pre-existing; out of scope for that PR).
internal/infrastructure/depsdev/advisory.go—FetchAdvisoriesBatchreturnsmap[string]*AdvisoryDetailwith no error return. On a per-advisory fetch failure it logs at DEBUG and drops the entry:The completion log is also DEBUG, so a partial result (e.g. severity data missing due to a transient 5xx) is indistinguishable downstream from "package has no advisories". This can understate vulnerability severity silently.
Fix options
Acceptance