Skip to main content

Issue with vmm v4.2 API (updateVmById)

  • June 15, 2026
  • 8 replies
  • 52 views

Forum|alt.badge.img+1

 

Environment:

 

  • Prism Central with v4.2 API (pc.7.5.1.4 specifically), against AHV AOS 7.5.0.6 cluster
  • Using official Nutanix JavaScript SDKs:
    • @nutanix-api/vmm-js-client ^4.2.0
    • @nutanix-api/clustermgmt-js-client ^4.2.0
    • Node.js v14+

Problem:

 

When attempting to update VM resources (CPU sockets, memory) or boot configuration using the v4.2 updateVmById API endpoint, the operation consistently fails with:

Failed to perform the operation on the VM with UUID 'xxx',  due to an invalid argument with key 'createTime' and value 'EMPTY'. Code: VMM-30102

 

What We're Attempting:

// Fetch current VM state
const vmResponse = await vmApi.getVmById(vmUuid);
const vmData = vmResponse.data.data;
const eTag = vmData.$reserved?.ETag;

// Modify resource allocation
vmData.numSockets = 2;
vmData.memorySizeBytes = 2 * 1024 * 1024 * 1024;

// Send update with If-Match header
await vmApi.updateVmById(vmUuid, vmData, { 'If-Match': eTag });

 

What We've Tried (None Work):

 

1. Removing timestamp fields at top level:
   - Deleted createTime, lastUpdateTime, updateTime, tenantId
   - Still fails with same error

2. Removing all read-only fields at top level:
   - Deleted extId, all timestamps, $reserved, $unknownFields, generationUuid, biosUuid, powerState, links, metadata
   - Still fails

3. Removing runtime network information:
   - Deleted learnedIpAddresses from all NICs
   - Still fails

4. Recursive cleanup of ALL nested objects:
   - Implemented recursive function to remove all read-only fields at every level (disks, nics, cdRoms, bootConfig, etc.)
   - Still fails

5. Following Nutanix support guidance:
   - Support suggested sending "the whole modified VM object without stripping fields"
   - This also fails with the same error

Evidence This is an API Bug:

When performing the same operations through the Prism Central web UI, we observed that:
- The browser does NOT use PUT requests to /api/vmm/v4.2/ahv/config/vms/{vmId}
- This suggests the UI uses a different (working) endpoint that is not exposed in the v4.2 SDK
- Or the updateVmById endpoint has a fundamental bug with request validation

Additional Context:

The error message indicates the API sees createTime as 'EMPTY' even when:
- The field doesn't exist in our request payload (deleted)
- The field exists in our request with a valid timestamp value
- The field is recursively removed from all nested objects

This suggests the API may be:
1. Reconstructing or validating fields internally in a broken way
2. Looking for the field in unexpected locations
3. Using a different serialization path than what GET returns

Question:

Has anyone successfully used the v4.2 updateVmById endpoint to modify VM resources? If so, what payload structure works?

Is there an alternative endpoint we should be using for VM resource modifications that the browser UI is using?

Any guidance would be greatly appreciated as we've exhausted all documented approaches and support suggestions.

8 replies

Forum|alt.badge.img+1
  • Author
  • Trailblazer
  • June 15, 2026

Note: I’ve also tried with raw API requests from a REST client, with the same results.


jarrodl
Forum|alt.badge.img+2
  • Vanguard
  • June 16, 2026

Does the VM have any storage policies or attached volume groups? 
I have seem a similar error when I was trying to update the VM Configuration that had a volume group attached to it.

I would also encourage you to raise a support case, if this in indeed a bug with the API.

Additionally, if you have access to the PCVM or CVM, you use use ecli to see if the task is being registered.

 

Task troubleshooting:

  1. List all task ecli task.list
  2. Inspect a specific task (look for the Acropolis component) ecli task.get <uuid»

 

The output of the ecli task.get should hopefully give you a better justification as to why the task is failing (providing the task is being registered to begin with) 


Forum|alt.badge.img+1
  • Author
  • Trailblazer
  • June 16, 2026

Thanks for your reply. No, the VM has nothing special about it like that. The updateVmById command is accepted (the PUT call), and a task created, but that task fails with the error.

 

I've opened a support case, but they only suggested I "wait a bit after the VM is created" before trying to update it. I can run the modification hours/days after it's created and it still fails. 


jarrodl
Forum|alt.badge.img+2
  • Vanguard
  • June 16, 2026

Thanks for your reply. No, the VM has nothing special about it like that. The updateVmById command is accepted (the PUT call), and a task created, but that task fails with the error.

 

I've opened a support case, but they only suggested I "wait a bit after the VM is created" before trying to update it. I can run the modification hours/days after it's created and it still fails. 

Okay yeah go back to support and tell them that did not work. You have performed a decent amount of troubleshooting already, so be firm we support and escalate the case if you feel like support is not listening.

 

By any chance did you have a chance to look at the ecli task.get output?


Forum|alt.badge.img+1
  • Author
  • Trailblazer
  • June 16, 2026

Thanks for your reply. No, the VM has nothing special about it like that. The updateVmById command is accepted (the PUT call), and a task created, but that task fails with the error.

 

I've opened a support case, but they only suggested I "wait a bit after the VM is created" before trying to update it. I can run the modification hours/days after it's created and it still fails. 

Okay yeah go back to support and tell them that did not work. You have performed a decent amount of troubleshooting already, so be firm we support and escalate the case if you feel like support is not listening.

 

By any chance did you have a chance to look at the ecli task.get output?

The only extra bit of detail in the ecli output is this:
 

  "debug_info": "VM Invalid Argument Error: 30102\n  :createTime attribute is missing in the VmUpdate Arg.",

The task does not get past the Prism Central, it seems.


jarrodl
Forum|alt.badge.img+2
  • Vanguard
  • June 16, 2026

So back to square 1. Since it’s not getting past the PC, you will need support to help trace the request from the IKAT proxy downstream to find where it’s getting rejected. 


  • Nutanix Employee
  • June 16, 2026

When the body is a Vm instance, the SDK seems to be serializing it via vm.toJson(), which strips the read-only fields createTime/updateTime from the request body.
The v4.2 VM-update backend validates createTime as required and rejects the request, which is why the task fails with VMM-30102 createTime EMPTY.

As a quick fix to try - create the update body as a plain object (which preserves createTime and avoids the models toJson() stripping).

const vmResponse = await vmApi.getVmById(vmUuid);
const vmData = vmResponse.data.data;
const eTag = vmData.$reserved?.ETag;
const payload = { ...vmData, numSockets: 2, memorySizeBytes: 2 * 1024 * 1024 * 1024 };
await vmApi.updateVmById(vmUuid, payload, { 'If-Match': eTag });

 


Forum|alt.badge.img+1
  • Author
  • Trailblazer
  • June 16, 2026

When the body is a Vm instance, the SDK seems to be serializing it via vm.toJson(), which strips the read-only fields createTime/updateTime from the request body.
The v4.2 VM-update backend validates createTime as required and rejects the request, which is why the task fails with VMM-30102 createTime EMPTY.

As a quick fix to try - create the update body as a plain object (which preserves createTime and avoids the model's toJson() stripping).

const vmResponse = await vmApi.getVmById(vmUuid);
const vmData = vmResponse.data.data;
const eTag = vmData.$reserved?.ETag;
const payload = { ...vmData, numSockets: 2, memorySizeBytes: 2 * 1024 * 1024 * 1024 };
await vmApi.updateVmById(vmUuid, payload, { 'If-Match': eTag });

 

Bingo - that worked! Many thanks!

      // Fetch current VM state and ETag
const vmResponseForResource = await apis.vmApi.getVmById(vmUuid);
const vmDataForResource = vmResponseForResource.data.data;
const vmETagForResource = vmDataForResource.$reserved?.ETag;

// Create new payload with spread operator and updated values (forum user suggestion)
const payload = {
...vmDataForResource,
numSockets: finalSockets,
memorySizeBytes: finalRamGib * 1024 * 1024 * 1024
};
debug_main("Updated sockets to %d and memory to %d GiB", finalSockets, finalRamGib);

if (debug_main.enabled) {
debug_main("Payload for resource adjustment: %s", JSON.stringify(payload, null, 2));
}

// Send the update
const resourceUpdateResponse = await apis.vmApi.updateVmById(vmUuid, payload, { 'If-Match': vmETagForResource });