Summary
Every call to GET /api/v0/bills/{id}/graphs/bits returns HTTP 500 since the upgrade to 26.5.0. The 26.4.x line worked. The same endpoint with the same parameters and same API token was returning SVG/PNG correctly until the auto-update.
Reproduce
- Generate an API token with read access.
- Call any bill’s graph endpoint:
curl -s -H "X-Auth-Token: $TOKEN" -o /tmp/g -w "HTTP %{http_code}\n"
"https://librenms.example.com/api/v0/bills/77/graphs/bits?from=((((
(((date +%s) - 604800))&to=$(date +%s)&width=900&height=260"
cat /tmp/grs/
Returns:
HTTP 500
{"message":"Server Error"}
Confirmed reproducible with multiple distinct bills (cdr and quota types), on different ports and devices. The /api/v0/bills/{id} (stats only) endpoint still works — only the graph subroute crashes.
Stack trace from /opt/librenms/logs/librenms.log
The return type was tightened to non-nullable string in 26.5.0. But GraphParameters::defaultTitle() for bill graphs passes a new Device() (empty model — bills are aggregates of ports, not tied to a single device), so both $this->display and $this->hostname are null. The function returns null and the type check throws.
Suggested fix
Either:
a) Make displayName() tolerate null fields:
public function displayName(): string
{
return (string) ($this->display ?: $this->hostname ?: $this->ip ?: '');
}
b) Or, in GraphParameters::defaultTitle(), skip the device-title path when no device is associated.
(a) is the smaller patch and is what I’m running locally as a stop-gap.
Impact
The bill graph API endpoint is the documented way to embed bandwidth graphs in external tools (WHMCS modules, NOC dashboards, customer portals). 26.5.0 broke all of them at once.