I think the problem is somehow related to the fact that vRO scripting array properties are not exactly equivalent to normal Javascript array properties.
A possible workaround would be to collect device config specs not directly into spec.deviceChange property but into a temporary plain Javascript array, and assign the whole array to spec.deviceChange after the first loop.
Something like this:
System.log(u_vm.name) var spec = new VcVirtualMachineConfigSpec(); myDeviceChanges = []; // <- plain Javascript array var ix = 0; for each (var device in u_vm.config.hardware.device) { if (device instanceof VcVirtualDisk) { if (device.backing instanceof VcVirtualDiskFlatVer2BackingInfo) { var dsname = device.backing.datastore.name; var possibleLdev = dsname.substring(dsname.length-4, dsname.length); for each (var ldev in u_ldevs) { if (ldev == possibleLdev) { var devChange = new VcVirtualDeviceConfigSpec(); devChange.operation = VcVirtualDeviceConfigSpecOperation.remove; devChange.device = device; myDeviceChanges.push(devChange); System.log("Found " + dsname); // this prints the datastore name System.log("device: " + device.deviceInfo.label); // this prints the device label "Hard Disk #" } } } } } spec.deviceChange = myDeviceChanges; // <- assign collected device config specs at once for (var ix in spec.deviceChange) // have also tried a for each (var devChange in spec.deviceChange) ... { System.log('dev change:'); // this never prints System.log('dc op: ' + spec.deviceChange[ix].operation.value); // this never prints System.log('dev: ' + spec.deviceChange[ix].device.deviceInfo.summary); // this never prints } task = u_vm.reconfigVM_Task(spec); // this run successfully