NetBox Edition
NetBox Community
NetBox Version
v4.6.0
Python Version
3.14
Steps to Reproduce
Set of objects needed to trigger the bug (1 site, 2 circuits, 2 circuit terminations, 1 cable):
- Site
SITE_ID=$(curl -s -X POST "$NETBOX_URL/api/dcim/sites/" \
-H "Authorization: Bearer nbt_S7p6rjKm3IzY.$TOKEN" \
-H "Content-Type: application/json" \
--data '{"name":"Site-A","slug":"site-a","status":"active"}' | jq -r '.id')
- Provider and circuit type
PROVIDER_ID=$(curl -s -X POST "$NETBOX_URL/api/circuits/providers/" \
-H "Authorization: Bearer nbt_S7p6rjKm3IzY.$TOKEN" \
-H "Content-Type: application/json" \
--data '{"name":"Provider-A","slug":"provider-a"}' | jq -r '.id')
CT_ID=$(curl -s -X POST "$NETBOX_URL/api/circuits/circuit-types/" \
-H "Authorization: Bearer nbt_S7p6rjKm3IzY.$TOKEN" \
-H "Content-Type: application/json" \
--data '{"name":"Transport","slug":"transport"}' | jq -r '.id')
- Two circuits
CIRCUIT_1=$(curl -s -X POST "$NETBOX_URL/api/circuits/circuits/" \
-H "Authorization: Bearer nbt_S7p6rjKm3IzY.$TOKEN" \
-H "Content-Type: application/json" \
--data "{\"cid\":\"CIRCUIT-1\",\"provider\":$PROVIDER_ID,\"type\":$CT_ID}" | jq -r '.id')
CIRCUIT_2=$(curl -s -X POST "$NETBOX_URL/api/circuits/circuits/" \
-H "Authorization: Bearer nbt_S7p6rjKm3IzY.$TOKEN" \
-H "Content-Type: application/json" \
--data "{\"cid\":\"CIRCUIT-2\",\"provider\":$PROVIDER_ID,\"type\":$CT_ID}" | jq -r '.id')
- Two circuit terminations, both scoped to Site-A
TERM_1=$(curl -s -X POST "$NETBOX_URL/api/circuits/circuit-terminations/" \
-H "Authorization: Bearer nbt_S7p6rjKm3IzY.$TOKEN" \
-H "Content-Type: application/json" \
--data "{\"circuit\":$CIRCUIT_1,\"term_side\":\"Z\",\"termination_type\":\"dcim.site\",\"termination_id\":$SITE_ID}" | jq -r '.id')
TERM_2=$(curl -s -X POST "$NETBOX_URL/api/circuits/circuit-terminations/" \
-H "Authorization: Bearer nbt_S7p6rjKm3IzY.$TOKEN" \
-H "Content-Type: application/json" \
--data "{\"circuit\":$CIRCUIT_2,\"term_side\":\"A\",\"termination_type\":\"dcim.site\",\"termination_id\":$SITE_ID}" | jq -r '.id')
- Cable connecting both terminations
CABLE_ID=$(curl -s -X POST "$NETBOX_URL/api/dcim/cables/" \
-H "Authorization: Bearer nbt_S7p6rjKm3IzY.$TOKEN" \
-H "Content-Type: application/json" \
--data "{\"a_terminations\": [{\"object_type\": \"circuits.circuittermination\", \"object_id\": $TERM_1}],
\"b_terminations\": [{\"object_type\": \"circuits.circuittermination\", \"object_id\": $TERM_2}],
\"status\": \"connected\"}" | jq -r '.id')
- Verify the terminations are found by site_id (works correctly)
curl -s "$NETBOX_URL/api/circuits/circuit-terminations/?site_id=$SITE_ID" \
-H "Authorization: Bearer nbt_S7p6rjKm3IzY.$TOKEN" \
-H "Content-Type: application/json" \
| jq '{count}'
# "count": 2
- Try to find the cable by id and site_id (bug)
curl -s "$NETBOX_URL/api/dcim/cables/?id=$CABLE_ID&site_id=$SITE_ID" \
-H "Authorization: Bearer nbt_S7p6rjKm3IzY.$TOKEN" \
-H "Content-Type: application/json" \
| jq '{count}'
# "count": 0
Expected Behavior
GET /api/dcim/cables/?site_id=$SITE_ID should return the cable, since both its endpoints are circuits.circuittermination objects explicitly scoped to that site via termination_type: "dcim.site".
Observed Behavior
GET /api/dcim/cables/?site_id=$SITE_ID returns count: 0.
The same site_id filter applied to circuit terminations correctly returns both terminations (count: 2), confirming the underlying data is correct and the issue is in the cable filter.
The filter does work correctly when at least one cable endpoint is a device component (dcim.interface, dcim.frontport, dcim.rearport, etc.). The issue is specific to cables where both endpoints are circuits.circuittermination.
The same behavior is reproducible through the web UI: navigating to Cables and filtering by site returns no results for cables where both endpoints are circuit terminations.
Additionally, in a separate production environment running NetBox v4.4.5, the site_id filter on cables shows inconsistent results: at least one cable with circuits.circuittermination on both ends does appear when filtering by site, while at least one other cable with an equivalent topology does not. The working case could not be reproduced in a clean lab environment. The suspected cause is that the cable or its terminations were created under an older NetBox version (prior to v4.4.5).
NetBox Edition
NetBox Community
NetBox Version
v4.6.0
Python Version
3.14
Steps to Reproduce
Set of objects needed to trigger the bug (1 site, 2 circuits, 2 circuit terminations, 1 cable):
Expected Behavior
GET /api/dcim/cables/?site_id=$SITE_IDshould return the cable, since both its endpoints arecircuits.circuitterminationobjects explicitly scoped to that site viatermination_type: "dcim.site".Observed Behavior
GET /api/dcim/cables/?site_id=$SITE_IDreturnscount: 0.The same
site_idfilter applied to circuit terminations correctly returns both terminations (count: 2), confirming the underlying data is correct and the issue is in the cable filter.The filter does work correctly when at least one cable endpoint is a device component (
dcim.interface,dcim.frontport,dcim.rearport, etc.). The issue is specific to cables where both endpoints arecircuits.circuittermination.The same behavior is reproducible through the web UI: navigating to Cables and filtering by site returns no results for cables where both endpoints are circuit terminations.
Additionally, in a separate production environment running NetBox v4.4.5, the site_id filter on cables shows inconsistent results: at least one cable with circuits.circuittermination on both ends does appear when filtering by site, while at least one other cable with an equivalent topology does not. The working case could not be reproduced in a clean lab environment. The suspected cause is that the cable or its terminations were created under an older NetBox version (prior to v4.4.5).