Primary key must be an integer when adding primary_ip4 via API PATCH #2084

Closed
opened 2025-12-29 17:22:07 +01:00 by adam · 4 comments
Owner

Originally created by @LoneSnowMonkey on GitHub (Nov 3, 2018).

Thanks much for this project in general, and specifically adding webhooks recently. I'm accomplishing an amazing amount of documentation and automation as a result.

I have a workflow in AWX that is creating new vmware machines based of entries made in Netbox. It's awesome and everything so far has worked. That is for one catch: If I try to take the newly assigned IP address and update netbox to make it the Primary IP the task fails. Depending on what I do either my PATCH results in a 200 with no difference in state, or I get a Primary key must be an integer error. This seems very similar to issue 2310. I have replicated the issue in both my dev and production systems.

I'm not much of a coder, and new to interacting with devs over Github, so apologies if I missed something.

Environment

  • Python version: 3.6.6 (dev) and 3.4.5 (prod)
  • NetBox version: 2.4.6 (dev) and 2.4.4 (prod)
  • OS: Ubuntu 18.04.1 (dev) and Centos 7.5 (prod)

Steps to Reproduce

curl -X PATCH -H "Authorization: Token APITOKEN" -H "Content-Type: application/json" -H "Accept: application/json; indent=4" https://NETBOX HOST/api/virtualization/virtual-machines/<vmid>/ --data '{"primary_ip4": {"address": "x.x.x.x/24"}}'

Expected Behavior

Netbox vm record is updated with the specified Primary IP.

Observed Behavior

{ "primary_ip4": [ "Primary key must be an integer" ] }

I have gone as far as adding it through the web UI, doing a GET and pasting the exact text into my PATCH after reseting that field, to no effect. Based off of another earlier issue I saw, if there is a Primary IP set and I PATCH with primary_ip4 as null it does in fact remove the record. FWIW.

Originally created by @LoneSnowMonkey on GitHub (Nov 3, 2018). Thanks much for this project in general, and specifically adding webhooks recently. I'm accomplishing an amazing amount of documentation and automation as a result. I have a workflow in AWX that is creating new vmware machines based of entries made in Netbox. It's awesome and everything so far has worked. That is for one catch: If I try to take the newly assigned IP address and update netbox to make it the Primary IP the task fails. Depending on what I do either my PATCH results in a 200 with no difference in state, or I get a **Primary key must be an integer** error. This seems very similar to [issue 2310](https://github.com/digitalocean/netbox/issues/2310). I have replicated the issue in both my dev and production systems. I'm not much of a coder, and new to interacting with devs over Github, so apologies if I missed something. ### Environment * Python version: 3.6.6 (dev) and 3.4.5 (prod) * NetBox version: 2.4.6 (dev) and 2.4.4 (prod) * OS: Ubuntu 18.04.1 (dev) and Centos 7.5 (prod) ### Steps to Reproduce `curl -X PATCH -H "Authorization: Token APITOKEN" -H "Content-Type: application/json" -H "Accept: application/json; indent=4" https://NETBOX HOST/api/virtualization/virtual-machines/<vmid>/ --data '{"primary_ip4": {"address": "x.x.x.x/24"}}'` ### Expected Behavior Netbox vm record is updated with the specified Primary IP. ### Observed Behavior `{ "primary_ip4": [ "Primary key must be an integer" ] }` I have gone as far as adding it through the web UI, doing a GET and pasting the exact text into my PATCH after reseting that field, to no effect. Based off of another earlier issue I saw, if there is a Primary IP set and I PATCH with primary_ip4 as null it does in fact remove the record. FWIW.
adam closed this issue 2025-12-29 17:22:07 +01:00
Author
Owner

@lampwins commented on GitHub (Nov 3, 2018):

I see a couple of problems in your workflow. You have not mentioned anything about the IP address being assigned to an Interface on the Virtual Machine beforehand. NetBox models the real world, and IP addresses are assigned to Interfaces, not Virtual Machines. NetBox provides a functionality to choose one IPv4 and/or IPv6 address from those assigned to VM interfaces, as the "primary" of the VM. That said, your flow should be this:

  1. Create Virtual Machine
  2. Create Interface(s) on Virtual Machine
  3. Assign/Create IP Address(es) assigned to VM Interface(s)
  4. Patch the Virtual Machine with only the integer ID of the IPAddress you wish to set to the primary_ip4 of the VM

Keeping in mind that for step 4 to work, the IP address object must already exist and be assigned to an Interface of the VM.

From the API docs:

Related objects (e.g. ForeignKey fields) are represented using a nested serializer. A nested serializer provides a minimal representation of an object, including only its URL and enough information to construct its name. When performing write api actions (POST, PUT, and PATCH), any ForeignKey relationships do not use the nested serializer, instead you will pass just the integer ID of the related model.

So the error is nudging you in the right direction. Instead of passing a nested representation of the IPAddress as you have in your example, you need to instead pass just the integer ID of that object, like so: {"primary_ip4": 735}.

@lampwins commented on GitHub (Nov 3, 2018): I see a couple of problems in your workflow. You have not mentioned anything about the IP address being assigned to an Interface on the Virtual Machine beforehand. NetBox models the real world, and IP addresses are assigned to Interfaces, not Virtual Machines. NetBox provides a functionality to choose one IPv4 and/or IPv6 address from those assigned to VM interfaces, as the "primary" of the VM. That said, your flow should be this: 1. Create Virtual Machine 2. Create Interface(s) on Virtual Machine 3. Assign/Create IP Address(es) assigned to VM Interface(s) 4. Patch the Virtual Machine with _only the integer ID_ of the `IPAddress` you wish to set to the `primary_ip4` of the VM Keeping in mind that for step 4 to work, the IP address object must already exist and be assigned to an Interface of the VM. From the API [docs](https://netbox.readthedocs.io/en/stable/api/overview/): > Related objects (e.g. ForeignKey fields) are represented using a nested serializer. A nested serializer provides a minimal representation of an object, including only its URL and enough information to construct its name. When performing write api actions (POST, PUT, and PATCH), any ForeignKey relationships do not use the nested serializer, instead you will pass just the integer ID of the related model. So the error is nudging you in the right direction. Instead of passing a nested representation of the `IPAddress` as you have in your example, you need to instead pass just the integer ID of that object, like so: `{"primary_ip4": 735}`.
Author
Owner

@LoneSnowMonkey commented on GitHub (Nov 3, 2018):

Yes, I understand this, that is exactly the workflow I am using. The last job that runs when creating a VM is to take the id or address (tried both) for the newly allocated IP address and try an PATCH the VM's primary_ip with it:

curl -X PATCH -H "Authorization: Token API TOKEN" -H "Content-Type: application/json" -H "Accept: application/json; indent=4" https://NETBOXHOST/api/virtualization/irtual-machines/<vmid>/ --data '{"primary_ip4": {"id": 1220}}'

{ "primary_ip4": [ "Primary key must be an integer" ] }

Using an integer is what makes sense to me. The reason I chose to mention address specifically in this message is the API documentation in /api/docs for doing this has a red star next to address, meaning "required". I figured it was wrong, but I'd rather error on the side of what the docs say, than what I 'think' is right. I have tried either and both, same outcome. As mentioned earlier I even added the Primary IP into my VM via the web GUI, did a GET, and pasted that completed block into my PATCH after removing the Primary IP, to no effect. In that case I get a 200, the full config for the VM dumped out and primary_ip and primary_ip4 are all still null.

The fact that this exact problem (I haven't tried for values other than primary_ip) was reported as bugged and fixed in August gave a feeling that it might be the same sort of thing. I'll try and load the version reported as patched and see if I have the same outcome.

@LoneSnowMonkey commented on GitHub (Nov 3, 2018): Yes, I understand this, that is exactly the workflow I am using. The last job that runs when creating a VM is to take the id or address (tried both) for the newly allocated IP address and try an PATCH the VM's primary_ip with it: `curl -X PATCH -H "Authorization: Token API TOKEN" -H "Content-Type: application/json" -H "Accept: application/json; indent=4" https://NETBOXHOST/api/virtualization/irtual-machines/<vmid>/ --data '{"primary_ip4": {"id": 1220}}'` `{ "primary_ip4": [ "Primary key must be an integer" ] }` Using an integer is what makes sense to me. The reason I chose to mention address specifically in this message is the API documentation in /api/docs for doing this has a red star next to address, meaning "required". I figured it was wrong, but I'd rather error on the side of what the docs say, than what I 'think' is right. I have tried either and both, same outcome. As mentioned earlier I even added the Primary IP into my VM via the web GUI, did a GET, and pasted that completed block into my PATCH after removing the Primary IP, to no effect. In that case I get a 200, the full config for the VM dumped out and primary_ip and primary_ip4 are all still null. The fact that this exact problem (I haven't tried for values other than primary_ip) was reported as bugged and fixed in August gave a feeling that it might be the same sort of thing. I'll try and load the version reported as patched and see if I have the same outcome.
Author
Owner

@lampwins commented on GitHub (Nov 3, 2018):

You are still not making the request correctly, do not nest the ID in any way.

This: '{"primary_ip4": {"id": 1220}}' should simply be this: '{"primary_ip4": 1220}'

Again, the error is telling you what is wrong. It is asking for an integer, but you are providing a dictionary.

The response from a GET request often makes use of nested serializers. Those nested serializers are never used in write actions.

@lampwins commented on GitHub (Nov 3, 2018): You are still not making the request correctly, do not nest the ID in any way. This: `'{"primary_ip4": {"id": 1220}}'` should simply be this: `'{"primary_ip4": 1220}'` Again, the error is telling you what is wrong. It is asking for an integer, but you are providing a dictionary. The response from a GET request often makes use of nested serializers. Those nested serializers are never used in write actions.
Author
Owner

@LoneSnowMonkey commented on GitHub (Nov 3, 2018):

Thanks lampwins, you're right. I'm new to dealing with APIs so in the past I have relied on pulling information for clues on how to format it to be summited. It also matched up with how I read the api/docs printout. I missed that there was no dict in your response. It worked just fine as a direct value. I appreciate your prompt response, as well as the the efforts of yourself and everyone else who contributes to Netbox. It's helping me realize a lot of things I've had in mind for the past year in my office.

Thanks and have a great weekend.

@LoneSnowMonkey commented on GitHub (Nov 3, 2018): Thanks lampwins, you're right. I'm new to dealing with APIs so in the past I have relied on pulling information for clues on how to format it to be summited. It also matched up with how I read the api/docs printout. I missed that there was no dict in your response. It worked just fine as a direct value. I appreciate your prompt response, as well as the the efforts of yourself and everyone else who contributes to Netbox. It's helping me realize a lot of things I've had in mind for the past year in my office. Thanks and have a great weekend.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/netbox#2084