GraphQL union type resolution for connected endpoints uses ConsolePortType instead of ConsolePort #317

Closed
opened 2026-04-05 16:25:41 +02:00 by MrUnknownDE · 0 comments
Owner

Originally created by @pheus on 2/18/2026

NetBox Edition

NetBox Community

NetBox Version

v4.5.3

Python Version

3.12

Steps to Reproduce

  1. Create a Console Port (any device, any name is fine).

  2. Open a Django shell (python manage.py shell).

  3. Run:

    from dcim.models import ConsolePort
    from dcim.graphql.gfk_mixins import ConnectedEndpointType
    
    port = ConsolePort.objects.first()
    ConnectedEndpointType.resolve_type(port, None)
    

Expected Behavior

ConnectedEndpointType.resolve_type() should return ConsolePortType for a ConsolePort model instance (consistent with the other branches and with InventoryItemComponentType.resolve_type() in the same module).

Observed Behavior

The method returns None for ConsolePort instances because it currently checks against the GraphQL type class:

# netbox/dcim/graphql/gfk_mixins.py
if type(instance) is ConsolePortType:
    return ConsolePortType

This means the ConsolePort branch is never taken, and union resolution relies on Strawberry’s fallback behavior. In my testing, the GraphQL query still happens to return ConsolePortType either way, but the resolver logic itself is incorrect/inconsistent and seems easy to trip up with future changes.

Proposed fix
Change the check to:

if type(instance) is ConsolePort:
    return ConsolePortType
*Originally created by @pheus on 2/18/2026* ### NetBox Edition NetBox Community ### NetBox Version v4.5.3 ### Python Version 3.12 ### Steps to Reproduce 1. Create a **Console Port** (any device, any name is fine). 2. Open a Django shell (`python manage.py shell`). 3. Run: ```python from dcim.models import ConsolePort from dcim.graphql.gfk_mixins import ConnectedEndpointType port = ConsolePort.objects.first() ConnectedEndpointType.resolve_type(port, None) ``` ### Expected Behavior `ConnectedEndpointType.resolve_type()` should return `ConsolePortType` for a `ConsolePort` model instance (consistent with the other branches and with `InventoryItemComponentType.resolve_type()` in the same module). ### Observed Behavior The method returns `None` for `ConsolePort` instances because it currently checks against the GraphQL type class: ```python # netbox/dcim/graphql/gfk_mixins.py if type(instance) is ConsolePortType: return ConsolePortType ``` This means the ConsolePort branch is never taken, and union resolution relies on Strawberry’s fallback behavior. In my testing, the GraphQL query still *happens* to return `ConsolePortType` either way, but the resolver logic itself is incorrect/inconsistent and seems easy to trip up with future changes. **Proposed fix** Change the check to: ```python if type(instance) is ConsolePort: return ConsolePortType ```
MrUnknownDE added the status: acceptedstatus: acceptedtype: bugstatus: acceptednetboxstatus: acceptedseverity: lowstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugtype: bugseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lowseverity: lownetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetbox labels 2026-04-05 16:25:46 +02:00
Sign in to join this conversation.
No Label netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low severity: low status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug type: bug
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github/netbox#317