You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by "DeviC3 (via GitHub)" <gi...@apache.org> on 2026/08/06 11:55:17 UTC
[I] createVMFromBackup throws NPE when the template has "Password Enabled" - the VM is created correctly but the API call fails [cloudstack]
DeviC3 opened a new issue, #13816:
URL: https://github.com/apache/cloudstack/issues/13816
### problem
Creating an instance from a backup (`createVMFromBackup` with `startvm=true`) fails with a `NullPointerException` in the API response, even though the instance is created correctly, its volumes are fully restored from the backup and the VM boots and runs.
The user-visible effect is a red error in the UI with no indication that the operation actually succeeded, and the generated password is not returned.
```
2026-08-05 18:37:06,819 ERROR [c.c.a.ApiAsyncJobDispatcher] (API-Job-Executor-20:[ctx-f743d928, job-138]) (logid:5f51fca6) Unexpected exception while executing org.apache.cloudstack.api.command.admin.vm.CreateVMFromBackupCmdByAdmin java.lang.NullPointerException: Cannot invoke "java.util.Map.get(Object)" because the return value of "com.cloud.utils.Pair.second()" is null
at com.cloud.vm.UserVmManagerImpl.startVirtualMachine(UserVmManagerImpl.java:5342)
at com.cloud.vm.UserVmManagerImpl.restoreVMFromBackup(UserVmManagerImpl.java:9848)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:569)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215)
at jdk.proxy3/jdk.proxy3.$Proxy202.restoreVMFromBackup(Unknown Source)
at org.apache.cloudstack.api.command.user.vm.CreateVMFromBackupCmd.execute(CreateVMFromBackupCmd.java:124)
at com.cloud.api.ApiDispatcher.dispatch(ApiDispatcher.java:173)
at com.cloud.api.ApiAsyncJobDispatcher.runJob(ApiAsyncJobDispatcher.java:110)
at org.apache.cloudstack.framework.jobs.impl.AsyncJobManagerImpl$5.runInContext(AsyncJobManagerImpl.java:698)
...
2026-08-05 18:37:06,820 DEBUG [o.a.c.f.j.i.AsyncJobManagerImpl] (API-Job-Executor-20:[ctx-f743d928, job-138]) (logid:5f51fca6) Complete async job-138, jobStatus: FAILED, resultCode: 530, result: {"uuidList":[],"errorcode":"530","errortext":"Cannot invoke \"java.util.Map.get(Object)\" because the return value of \"com.cloud.utils.Pair.second()\" is null"}
```
### Root cause
The trigger is a source VM whose template has `enable_password = 1` ("Password Enabled").
`restoreVMFromBackup` starts the VM **twice**:
1. First with `Param.ReturnAfterVolumePrepare = true` - [UserVmManagerImpl.java#L9808](https://github.com/apache/cloudstack/blob/4.22.1.0/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java#L9808). On this run `vm.isUpdateParameters()` is still `true`, so the params map is built ([L5795](https://github.com/apache/cloudstack/blob/4.22.1.0/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java#L5794-L5795)) and the flag is then cleared - `vm.setUpdateParameters(false)` at [L5843](https://github.com/apache/cloudstack/blob/4.22.1.0/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java#L5835-L5845).
2. Then, when `cmd.getStartVm()` is true, it performs the real start - [UserVmManagerImpl.java#L9848](https://github.com/apache/cloudstack/blob/4.22.1.0/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java#L9848).
On the second run `vm.isUpdateParameters()` is already `false`, so `params` stays `null` and the returned `Pair.second()` is `null`. The private `startVirtualMachine` overload then dereferences it unconditionally whenever the template has a password enabled - [UserVmManagerImpl.java#L5339-L5342](https://github.com/apache/cloudstack/blob/4.22.1.0/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java#L5339-L5343):
```java
VMTemplateVO template = _templateDao.findByIdIncludingRemoved(vm.getTemplateId());
if (template.isEnablePassword()) {
// this value is not being sent to the backend; need only for api display purposes
vm.setPassword((String)vmParamPair.second().get(VirtualMachineProfile.Param.VmPassword));
}
```
The exception is thrown **outside** the `try` block at [L9806-L9829](https://github.com/apache/cloudstack/blob/4.22.1.0/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java#L9806-L9829), so the `expunge()` cleanup in the catch does not run. That is why the VM survives in a correct, running state and only the API response fails - the `VM.CREATE.FROM.BACKUP` event itself is recorded as `Completed`.
The same unguarded dereference is present on `main` - [UserVmManagerImpl.java#L5597](https://github.com/apache/cloudstack/blob/main/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java#L5597).
### versions
- CloudStack **4.22.1.0** (packages `cloudstack-management-4.22.1.0-1`, `cloudstack-agent-4.22.1.0-1`); code inspected on tag `4.22.1.0` and on `main`
- Hypervisor: **KVM** on AlmaLinux 9.8, `qemu-kvm 10.1.0`, `libvirt 11.10.0`, OpenJDK 17.0.20
- Primary storage: **Ceph RBD** (Ceph 20.2.2)
- Backup provider: **NAS Backup & Recovery** (`backup.framework.provider.plugin = nas`), repository on an NFS export backed by CephFS
- Database: MySQL 8.0.46
- 3 management servers, single advanced zone
### The steps to reproduce the bug
1. Register a template with **Password Enabled = true** (`enable_password = 1`).
2. Deploy an instance from that template.
3. Enable the backup framework with the `nas` provider, assign a backup offering to the instance and take a backup.
4. Go to **Backups**, select the backup, choose **Create Instance from Backup** and leave **Start Instance = Yes**.
5. The job fails with the NPE above (`errorcode 530`), but `listVirtualMachines` shows the new instance in state `Running` with its volumes correctly restored.
The bug does not appear when the template has Password Enabled unset, or when **Start Instance = No** is selected.
### What to do about it?
Workaround for users: create the instance with **Start Instance = No** and start it afterwards - the manual start path (`StartVMCmd`) only uses `Pair.first()`, so it is unaffected.
Minimal fix - guard the dereference at `UserVmManagerImpl.java:5342`:
```java
if (template.isEnablePassword() && vmParamPair.second() != null) {
vm.setPassword((String)vmParamPair.second().get(VirtualMachineProfile.Param.VmPassword));
}
```
A cleaner fix would be for `restoreVMFromBackup` to reuse the params map returned by the first `startVirtualMachine` call instead of letting the second call re-derive it from a flag the first call has already consumed - that would also make the generated password available in the API response, which is arguably the intended behaviour.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [I] createVMFromBackup throws NPE when the template has "Password Enabled" - the VM is created correctly but the API call fails [cloudstack]
Posted by "boring-cyborg[bot] (via GitHub)" <gi...@apache.org>.
boring-cyborg[bot] commented on issue #13816:
URL: https://github.com/apache/cloudstack/issues/13816#issuecomment-5204308440
Thanks for opening your first issue here! Be sure to follow the issue template!
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [I] createVMFromBackup throws NPE when the template has "Password Enabled" - the VM is created correctly but the API call fails [cloudstack]
Posted by "DaanHoogland (via GitHub)" <gi...@apache.org>.
DaanHoogland commented on issue #13816:
URL: https://github.com/apache/cloudstack/issues/13816#issuecomment-5266918965
please test the solution in #12771
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [I] createVMFromBackup throws NPE when the template has "Password Enabled" - the VM is created correctly but the API call fails [cloudstack]
Posted by "prashanthr2 (via GitHub)" <gi...@apache.org>.
prashanthr2 commented on issue #13816:
URL: https://github.com/apache/cloudstack/issues/13816#issuecomment-5218013306
Reproduced on 4.22.1.0.
The question is whether createVMFromBackup should issue a new password or whether the instance should inherit the backed-up guest. The oneline null guard proposed above is only correct if it inherits. If a new password is meant to be issued, the guard alone leaves the instance with a password that is set but never returned to the user and not retrievable afterwards.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [I] createVMFromBackup throws NPE when the template has "Password Enabled" - the VM is created correctly but the API call fails [cloudstack]
Posted by "DaanHoogland (via GitHub)" <gi...@apache.org>.
DaanHoogland closed issue #13816: createVMFromBackup throws NPE when the template has "Password Enabled" - the VM is created correctly but the API call fails
URL: https://github.com/apache/cloudstack/issues/13816
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [I] createVMFromBackup throws NPE when the template has "Password Enabled" - the VM is created correctly but the API call fails [cloudstack]
Posted by "DeviC3 (via GitHub)" <gi...@apache.org>.
DeviC3 commented on issue #13816:
URL: https://github.com/apache/cloudstack/issues/13816#issuecomment-5265183655
Thanks for reproducing it.
On the semantics question: a new password is already generated in this path today, it
just never reaches anyone. In the first startVirtualMachine call (ReturnAfterVolumePrepare
= true, L9808) vm.isUpdateParameters() is still true, so the params map is built with
Param.VmPassword and the flag is cleared at L5843. In orchestrateStart the early return
for ReturnAfterVolumePrepare sits after _networkMgr.prepare(...) (4.22.1.0, L1359-1377),
so the password has already gone to the password service before that call returns.
Two things follow, both read off the code and not yet confirmed on the wire:
- the null guard alone gives a running instance whose guest picks up a password nobody
ever sees; the current NPE at least fails loudly,
- Start Instance = No does not avoid it, since only the second start is gated on
getStartVm() - the first one always runs.
So the fix depends on the intent. If the instance should inherit (my reading for a backup
restore - the root volume is a block-level copy, so the credentials on disk are the source
VM's), the password param should not be generated in this path at all and the guard is
just defence in depth. If a new password is meant to be issued, the Pair from the first
call should be carried into the second one so the API returns the password that already
went to the router.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org