Customers are running into System.Management.Automation.PSInvalidOperationException: The pipeline was not run because a pipeline is already running. Pipelines cannot be run concurrently error when calling Add-AzVhd method from Az.Compute module. Looking at the stack trace, it's coming from the following method in Automation SDK: System.Management.Automation.Runspaces.PipelineBase.DoConcurrentCheck(Boolean syncCall, Object syncObject, Boolean isInLock)
However, we are not able to reproduce it every time. We are only able to reproduce it successfully around 20% of the time. We are not using any piping in our PS script. Could you guys help us out in determining what the problem might be?
No reliable reproduce method. Personally, I am unable to reproduce it, however another engineer is able to and he has around 20% repro rate.
# Cosine IOT Services Azure Internal Consumption
$subscriptionId='f9cb372a-8903-4370-9ce0-3042e3bb2cc8'
$rgSeed = "akstest" # TODO customize
$vmSeed = "0430c101a"
$vhdFolder = "C:\Users\jiria\Downloads"
$vhdFileName = "aks-vhd-2.0.20200815.0745.vhd"
$storageAccountName = "storage" + $rgSeed
$location = "westus2"
# $vmSize = "Standard_A2"
$vmSize = "Standard_NC6"
.\vm-create.ps1 $subscriptionId $rgSeed $vmSeed $vhdFolder $vhdFileName $storageAccountName $location $vmSize
No error
error: Exception - System.Management.Automation.PSInvalidOperationException: The pipeline was not run because a pipeline is already running. Pipelines cannot be run concurrently.
Please ask in https://github.com/Azure/azure-powershell
GitHub
Microsoft Azure PowerShell. Contribute to Azure/azure-powershell development by creating an account on GitHub.
@iSazonov, I was told by Azure-PS team to come here. They weren't sure what the best way to instantiate PowerShell class. What is the difference between calling Create() vs Create(RunspaceMode.NewRunSpace)?
@MS-syh2qs Please add more info as our issue template ask. Also please add a reference to your discussion with Azure-PS team.
We are not using any piping in our PS script
A pipeline here is what runs the commands. The error message means you're trying to run multiple commands at the same time on the same thread (i.e. in the same runspace).
In the snippet and error message you've shown, there isn't enough information to establish what's going on. In particular we don't know what cmdlets are being used, where the error occurs or any other details about the error. We need:
vm-create.ps1 and any other scripts being called -- we need to know the whole program you're runningGet-Error or $error[0] | fl * -force after you reproduceI think they mentioned the cmdlet they ran; Add-AzVhd -- I suspect the cmdlet is doing something... unwise... internally if that's all they ran.
@rjmholt,
Here's the script:
vm-create.txt
This is the full stack trace:
DEBUG: AzureQoSEvent: CommandName - Add-AzVhd; IsSuccess - False; Duration - 00:56:52.8136956;; Exception - System.Management.Automation.PSInvalidOperationException: The pipeline was not
run because a pipeline is already running. Pipelines cannot be run concurrently.
at System.Management.Automation.Runspaces.PipelineBase.DoConcurrentCheck(Boolean syncCall, Object syncObject, Boolean isInLock)
at System.Management.Automation.Runspaces.RunspaceBase.DoConcurrentCheckAndAddToRunningPipelines(PipelineBase pipeline, Boolean syncCall)
at System.Management.Automation.Runspaces.PipelineBase.CoreInvoke(IEnumerable input, Boolean syncCall)
at System.Management.Automation.Runspaces.PipelineBase.Invoke(IEnumerable input)
at System.Management.Automation.PowerShell.Worker.ConstructPipelineAndDoWork(Runspace rs, Boolean performSyncInvoke)
at System.Management.Automation.PowerShell.Worker.CreateRunspaceIfNeededAndDoWork(Runspace rsToUse, Boolean isSync)
at System.Management.Automation.PowerShell.CoreInvokeHelper[TInput,TOutput](PSDataCollection`1 input, PSDataCollection`1 output, PSInvocationSettings settings)
at System.Management.Automation.PowerShell.CoreInvoke[TInput,TOutput](PSDataCollection`1 input, PSDataCollection`1 output, PSInvocationSettings settings)
at System.Management.Automation.PowerShell.Invoke(IEnumerable input, PSInvocationSettings settings)
at Microsoft.Azure.Commands.Compute.Models.PSSyncOutputEvents.LogProgressComplete(Int32 activityId, String activity)
at Microsoft.Azure.Commands.Compute.Models.PSSyncOutputEvents.ProgressUploadComplete(TimeSpan elapsed)
at Microsoft.WindowsAzure.Commands.Sync.ProgressTracker.Dispose(Boolean disposing)
at Microsoft.WindowsAzure.Commands.Sync.ProgressTracker.Dispose()
at Microsoft.WindowsAzure.Commands.Sync.Upload.BlobSynchronizer.Synchronize()
at Microsoft.Azure.Commands.Compute.Models.VhdUploaderModel.Upload(UploadParameters uploadParameters)
at Microsoft.Azure.Commands.Compute.StorageServices.AddAzureVhdCommand.ExecuteCmdlet()
at Microsoft.WindowsAzure.Commands.Utilities.Common.AzurePSCmdlet.ProcessRecord();
Thanks for that.
Here is the relevant code in Azure PowerShell.
This is expected behaviour from the PowerShell engine; trying to run multiple PowerShells at the same time on the same runspace will result in this error.
Azure PowerShell needs to create a nested PowerShell instance to do this when calling from the pipeline thread -- this can be done, since we are under the ProcessRecord() call stack. In cases where they are calling from a different thread, they need to come up with another way to synchronise their use of the original runspace.
I suggest if you have the original Azure PowerShell issue, we should move this back to there and reopen it, or otherwise open a new issue on Azure PowerShell.
I was told by Azure-PS team to come here
Apologies, I misunderstood this as "the AzPS team told me the issue lies with PowerShell" rather than "I'm trying to help the AzPS team fix this and I'm here for answers".
Basically the fix depends on:
Basically, if this is always being called from the original cmdlet thread under the callstack of BeginProcessing()/ProcessRecord()/EndProcessing(), then it's enough just to use a nested PowerShell instance:
using (var pwsh = PowerShell.Create(RunspaceMode.CurrentRunspace))
{
pwsh.AddCommand("Write-Progress")
.AddParameter("Id", activityId)
.AddParameter("Activity", activity)
.AddParameter("Status", Rsrc.PSSyncOutputEventsLogProgressCompleteCompleted)
.AddParameter("Completed")
.Invoke();
}
However, if this is being called from multiple threads as I suspect, then we need to understand the requirements better to come up with a better mechanism to synchronise usage or to otherwise manage the concurrent use of PowerShell resources. Some avenues available are:
PSThreadOptions to create that runspaceIn this particular case though, we're trying to write progress, which is a user-facing UI task (i.e. very much a foreground operation). In PowerShell, you don't need to create and execute a PowerShell instance for this. Instead, you can use the Host's UI property ($Host.UI, also available in PSCmdlets with the Host property) to write things whenever you like -- no synchronisation required. But this is a bad idea, because writing output to the screen while the user is doing something else is at best a strange experience and at worst totally mangles their terminal.
So my recommendation is:
PSSyncOutputEvents is being used.PSSyncOutputEvents and why?PowerShell instance@rjmholt,
Apologies, I misunderstood this as "the AzPS team told me the issue lies with PowerShell" rather than "I'm trying to help the AzPS team fix this and I'm here for answers".
Yeah sorry about that, I wasn't very clear.
Thank you for the detailed response, my team will take a look where you've pointed to.
Most helpful comment
A pipeline here is what runs the commands. The error message means you're trying to run multiple commands at the same time on the same thread (i.e. in the same runspace).
In the snippet and error message you've shown, there isn't enough information to establish what's going on. In particular we don't know what cmdlets are being used, where the error occurs or any other details about the error. We need:
vm-create.ps1and any other scripts being called -- we need to know the whole program you're runningGet-Erroror$error[0] | fl * -forceafter you reproduce