GraphQL API Improperly formatting choice fields #8948

Closed
opened 2025-12-29 20:43:12 +01:00 by adam · 4 comments
Owner

Originally created by @tyler-8 on GitHub (Dec 11, 2023).

Deployment Type

Self-hosted

NetBox Version

v3.6.6
v3.3.10

Python Version

3.10

Steps to Reproduce

  1. Create a Device (Router1), using an arbitrary site (australia in this example) & device type
  2. Create an Interface Gig1 on Router1 with a type of 1000base-x-sfp
  3. Using the GraphQL API, run this query
query {
  device_list(site:"australia", name: "Router1") {
    name
    site {
      name
      status
    }
    status
    interfaces {
      name
      type
      enabled
    }
  }
}

Expected Behavior

Expected output:

{
  "data": {
    "device_list": [
      {
        "name": "Router1",
        "site": {
          "name": "Australia",
          "status": "active"  // site status value is lowercase to match raw value
        },
        "status": "active",  // device status value is lowercase to match raw value
        "interfaces": [
          {
            "name": "Gig1",
            "type": "1000base-x-sfp",  // interface type matches value & casing of raw value
            "enabled": true
          }
        ]
      }
    ]
  }
}

Observed Behavior

{
  "data": {
    "device_list": [
      {
        "name": "Router1",
        "site": {
          "name": "Australia",
          "status": "ACTIVE"  // site status is uppercase
        },
        "status": "ACTIVE",  // device status is uppercase
        "interfaces": [
          {
            "name": "Gig1",
            "type": "A_1000BASE_X_SFP",  // interface type value as "A_" prepended, hyphens are now underscores, and all uppercase.
            "enabled": true
          }
        ]
      }
    ]
  }
}

Status & type field have incorrect formatting and values. This makes it more involved to clean up the data to match back to NetBox itself. For example, when reading data with GraphQL and writing data with REST.

I think any interface type value that starts with a number is getting "A_" prepended.

A_40GBASE_X_QSFPP

Example output for type field using a wireless type and another non-numeric-starting value:

IEEE802_11AD
INFINIBAND_XDR

Originally created by @tyler-8 on GitHub (Dec 11, 2023). ### Deployment Type Self-hosted ### NetBox Version v3.6.6 v3.3.10 ### Python Version 3.10 ### Steps to Reproduce 1. Create a Device (Router1), using an arbitrary site (`australia` in this example) & device type 2. Create an Interface `Gig1` on `Router1` with a type of `1000base-x-sfp` 3. Using the GraphQL API, run this query ``` query { device_list(site:"australia", name: "Router1") { name site { name status } status interfaces { name type enabled } } } ``` ### Expected Behavior Expected output: ```jsonc { "data": { "device_list": [ { "name": "Router1", "site": { "name": "Australia", "status": "active" // site status value is lowercase to match raw value }, "status": "active", // device status value is lowercase to match raw value "interfaces": [ { "name": "Gig1", "type": "1000base-x-sfp", // interface type matches value & casing of raw value "enabled": true } ] } ] } } ``` ### Observed Behavior ```jsonc { "data": { "device_list": [ { "name": "Router1", "site": { "name": "Australia", "status": "ACTIVE" // site status is uppercase }, "status": "ACTIVE", // device status is uppercase "interfaces": [ { "name": "Gig1", "type": "A_1000BASE_X_SFP", // interface type value as "A_" prepended, hyphens are now underscores, and all uppercase. "enabled": true } ] } ] } } ``` Status & type field have incorrect formatting and values. This makes it more involved to clean up the data to match back to NetBox itself. For example, when reading data with GraphQL and writing data with REST. I think any interface type value that starts with a number is getting "A_" prepended. `A_40GBASE_X_QSFPP` Example output for `type` field using a wireless type and another non-numeric-starting value: `IEEE802_11AD` `INFINIBAND_XDR`
adam closed this issue 2025-12-29 20:43:13 +01:00
Author
Owner

@tyler-8 commented on GitHub (Dec 12, 2023):

It appears this is a behavior of graphene-Django and it can be disabled.

https://docs.graphene-python.org/projects/django/en/latest/queries/#choices-to-enum-conversion

IMO it should be since this essentially causes the GraphQL API to return "invalid" data values.

More detail from old issue on the graphene-django repo: https://github.com/graphql-python/graphene-django/issues/67

@tyler-8 commented on GitHub (Dec 12, 2023): It appears this is a behavior of graphene-Django and it can be disabled. https://docs.graphene-python.org/projects/django/en/latest/queries/#choices-to-enum-conversion IMO it should be since this essentially causes the GraphQL API to return "invalid" data values. More detail from old issue on the graphene-django repo: https://github.com/graphql-python/graphene-django/issues/67
Author
Owner

@tyler-8 commented on GitHub (Dec 12, 2023):

Here's an example of how this would be fixed using the option documented in my previous post:

class InterfaceType(IPAddressesMixin, ComponentObjectType, CabledObjectMixin, PathEndpointMixin):

    class Meta:
        model = models.Interface
        exclude = ('_path',)
        filterset_class = filtersets.InterfaceFilterSet
        convert_choices_to_enum = False  # Setting to disable Enum conversion

    def resolve_poe_mode(self, info):
        return self.poe_mode or None

    def resolve_poe_type(self, info):
        return self.poe_type or None

    def resolve_mode(self, info):
        return self.mode or None

    def resolve_rf_role(self, info):
        return self.rf_role or None

    def resolve_rf_channel(self, info):
        return self.rf_channel or None
@tyler-8 commented on GitHub (Dec 12, 2023): Here's an example of how this would be fixed using the option documented in my previous post: ```python class InterfaceType(IPAddressesMixin, ComponentObjectType, CabledObjectMixin, PathEndpointMixin): class Meta: model = models.Interface exclude = ('_path',) filterset_class = filtersets.InterfaceFilterSet convert_choices_to_enum = False # Setting to disable Enum conversion def resolve_poe_mode(self, info): return self.poe_mode or None def resolve_poe_type(self, info): return self.poe_type or None def resolve_mode(self, info): return self.mode or None def resolve_rf_role(self, info): return self.rf_role or None def resolve_rf_channel(self, info): return self.rf_channel or None ```
Author
Owner

@github-actions[bot] commented on GitHub (Mar 26, 2024):

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. NetBox is governed by a small group of core maintainers which means not all opened issues may receive direct feedback. Do not attempt to circumvent this process by "bumping" the issue; doing so will result in its immediate closure and you may be barred from participating in any future discussions. Please see our contributing guide.

@github-actions[bot] commented on GitHub (Mar 26, 2024): This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. NetBox is governed by a small group of core maintainers which means not all opened issues may receive direct feedback. **Do not** attempt to circumvent this process by "bumping" the issue; doing so will result in its immediate closure and you may be barred from participating in any future discussions. Please see our [contributing guide](https://github.com/netbox-community/netbox/blob/develop/CONTRIBUTING.md).
Author
Owner

@tyler-8 commented on GitHub (Mar 26, 2024):

Since GitHub reminded me about this; and just an FYI for any future users coming across this issue:

It's no longer relevant given the migration to Strawberry that's coming in NetBox 4.0.

@tyler-8 commented on GitHub (Mar 26, 2024): Since GitHub reminded me about this; and just an FYI for any future users coming across this issue: It's no longer relevant given the [migration to Strawberry](https://github.com/netbox-community/netbox/issues/9856) that's coming in NetBox 4.0.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/netbox#8948