No longer possible to get a list of objects by ID in GraphQL API (Netbox 4.3) #11343

Closed
opened 2025-12-29 21:43:54 +01:00 by adam · 7 comments
Owner

Originally created by @mraerino on GitHub (Jul 3, 2025).

Deployment Type

Self-hosted

NetBox Version

v4.3.3

Python Version

3.12

Steps to Reproduce

In Netbox 4.2.x it was possible to do a query like this. There is no equivalent in Netbox 4.3

query listDevicesByID($deviceIDs: [String!]) {
  device_list(filters: {id: {in_list: $deviceIDs}}) {
    id
    name
  }
}

Expected Behavior

I expect the GraphQL to allow me to fetch multiple objects based on a list of IDs

Observed Behavior

There is no filter option to list devices for multiple IDs

Originally created by @mraerino on GitHub (Jul 3, 2025). ### Deployment Type Self-hosted ### NetBox Version v4.3.3 ### Python Version 3.12 ### Steps to Reproduce In Netbox 4.2.x it was possible to do a query like this. There is no equivalent in Netbox 4.3 ```gql query listDevicesByID($deviceIDs: [String!]) { device_list(filters: {id: {in_list: $deviceIDs}}) { id name } } ``` ### Expected Behavior I expect the GraphQL to allow me to fetch multiple objects based on a list of IDs ### Observed Behavior There is no filter option to list devices for multiple IDs
adam added the type: bugstatus: duplicatetopic: GraphQL labels 2025-12-29 21:43:54 +01:00
adam closed this issue 2025-12-29 21:43:54 +01:00
Author
Owner

@sleepinggenius2 commented on GitHub (Jul 3, 2025):

As a test, I tried changing the id fields on the BaseObjectTypeFilterMixin and ChangeLogFilterMixin classes in core.graphql.filter_mixins from id: ID | None = strawberry.UNSET to id: FilterLookup[ID] | None = strawberry.UNSET and that seems to resolve the issue. Unfortunately, similar code seems to be used on all the _id fields across every model, so whatever the resolution for this issue is, it would need to be applied to them as well.

@sleepinggenius2 commented on GitHub (Jul 3, 2025): As a test, I tried changing the `id` fields on the `BaseObjectTypeFilterMixin` and `ChangeLogFilterMixin` classes in `core.graphql.filter_mixins` from `id: ID | None = strawberry.UNSET` to `id: FilterLookup[ID] | None = strawberry.UNSET` and that seems to resolve the issue. Unfortunately, similar code seems to be used on all the `_id` fields across every model, so whatever the resolution for this issue is, it would need to be applied to them as well.
Author
Owner

@mraerino commented on GitHub (Jul 3, 2025):

and i guess this would be a breaking change, since existing queries would stop to work?

@mraerino commented on GitHub (Jul 3, 2025): and i guess this would be a breaking change, since existing queries would stop to work?
Author
Owner

@sleepinggenius2 commented on GitHub (Jul 3, 2025):

I guess it would depend on whether your existing query was written for 4.3 or earlier. For pre-4.3 queries, a change like that would allow you to continue to use your existing query unchanged. For a query that was written specifically for 4.3, then filters: {id: "123"} would need to be replaced by filters: {id: {exact: "123"}}, which would have matched the pre-4.3 syntax. Interestingly, it looks like that only applies to the id field, as any other _id fields did not seem to allow for filter expressions pre-4.3 either. So, your example I would consider a regression, but that would be new functionality for other _id fields, which would probably be considered an enhancement instead. With just the id change, for the _id fields, a filter like {device_type: {id: {in_list: ["1", "2"]}}} instead of {device_type_id: {in_list: ["1", "2"]}} looks like it could be used in 4.3 to accomplish the same thing without any changes to that part of the code. I also just tested to see if it would allow ID | FilterLookup[ID] | None to try to account for both scenarios, but that generates an error.

@sleepinggenius2 commented on GitHub (Jul 3, 2025): I guess it would depend on whether your existing query was written for 4.3 or earlier. For pre-4.3 queries, a change like that would allow you to continue to use your existing query unchanged. For a query that was written specifically for 4.3, then `filters: {id: "123"}` would need to be replaced by `filters: {id: {exact: "123"}}`, which would have matched the pre-4.3 syntax. Interestingly, it looks like that only applies to the `id` field, as any other `_id` fields did not seem to allow for filter expressions pre-4.3 either. So, your example I would consider a regression, but that would be new functionality for other `_id` fields, which would probably be considered an enhancement instead. With just the `id` change, for the `_id` fields, a filter like `{device_type: {id: {in_list: ["1", "2"]}}}` instead of `{device_type_id: {in_list: ["1", "2"]}}` looks like it could be used in 4.3 to accomplish the same thing without any changes to that part of the code. I also just tested to see if it would allow `ID | FilterLookup[ID] | None` to try to account for both scenarios, but that generates an error.
Author
Owner

@AdilsonTorres commented on GitHub (Aug 15, 2025):

Prior to version 4 (3.7.X), I was using queries with lists on multiple fields. In version 4.3.X, this no longer seems possible for the ID field. To reduce the number of requests, I believe it would be better to allow something like: filters: {id: {exact: "123"} and {device_type: {id: {in_list: ["1", "2"]}}} rather than not being able to use lists on IDs at all.

@AdilsonTorres commented on GitHub (Aug 15, 2025): Prior to version 4 (3.7.X), I was using queries with lists on multiple fields. In version 4.3.X, this no longer seems possible for the ID field. To reduce the number of requests, I believe it would be better to allow something like: ` filters: {id: {exact: "123"}` and `{device_type: {id: {in_list: ["1", "2"]}}}` rather than not being able to use lists on IDs at all.
Author
Owner

@heroin-moose commented on GitHub (Aug 22, 2025):

According to Strawberry documentation it should be possible to filter IDs by list:

input IDBaseFilterLookup {
  exact: ID
  isNull: Boolean
  inList: [String!]
}

So I'm not sure why it does not work, but it does not:

query($id_list: [String!]) {
  interface_list(
    filters: {
      id: { in_list: $id_list }
    }
  ) {
    id
  }
}

Error:

"message": "ID cannot represent a non-string and non-integer value: {in_list: $id_list}",
@heroin-moose commented on GitHub (Aug 22, 2025): According to Strawberry [documentation](https://strawberry.rocks/docs/django/guide/filters#lookups) it should be possible to filter IDs by list: ``` input IDBaseFilterLookup { exact: ID isNull: Boolean inList: [String!] } ``` So I'm not sure why it does not work, but it does not: ``` query($id_list: [String!]) { interface_list( filters: { id: { in_list: $id_list } } ) { id } } ``` Error: ``` "message": "ID cannot represent a non-string and non-integer value: {in_list: $id_list}", ```
Author
Owner

@tyler-8 commented on GitHub (Aug 30, 2025):

Related https://github.com/netbox-community/netbox/issues/19338

@tyler-8 commented on GitHub (Aug 30, 2025): Related https://github.com/netbox-community/netbox/issues/19338
Author
Owner

@jeremystretch commented on GitHub (Sep 4, 2025):

This is being addressed under FR #19338.

@jeremystretch commented on GitHub (Sep 4, 2025): This is being addressed under FR #19338.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/netbox#11343