Camunda 7 scripting - race conditions while setting a variable?

I am new to Camunda and I have a workflow with a sub-process that accesses parent variables.

Specifically, the parent does this in a script task (groovy code):

class Result {
    Boolean canProceed
    String errorMessage
}

Init();

def Init()
{
    def result = execution.hasVariable("result");
    if(result == false)
    {
        result = new Result();
//        execution.removeVariable("result");
        execution.setVariable("result", result);
    }
}

def setError(errorMessage)
{
    Init();
    def result = execution.getVariable("result");
    result.canProceed = false;
    result.errorMessage = errorMessage;
}

def setSuccess()
{
    Init();
    def result = execution.getVariable("result");
    result.canProceed = true;
    result.errorMessage = null;
}

And the sub-process calls the setSuccess() and setError("sth") functions.

The workflow does not contain any user tasks, so once I start a process instance, it executes and it gets done/destroyed, after I get the result variables back.

All is working fine when I call the workflow once at a time.
But when I bombard it with parallel calls, then I get weird errors revolving around variables.

This is the C# code that calls the workflow in parallel:

var camunda = CamundaClient.Create("http://localhost:8080/engine-rest");
var pd = camunda.ProcessDefinitions.ByKey("name");

var actionNames = new string[] {
	...
	...
	...
};

var repetition = 0;
var parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = 10 };
await Parallel.ForEachAsync(actionNames, parallelOptions, async (actionName, ct) => {
	var result = await PerformAction(actionName: actionName);
});

async Task<Result> PerformAction(string actionName)
{
	var businessKey = $"temp-id:{Guid.NewGuid()}";

	var camundaResult = await pd.StartProcessInstance(new Camunda.Api.Client.ProcessDefinition.StartProcessInstance
	{
		BusinessKey = businessKey,
		Variables =
		{
			{ "action", VariableValue.FromObject(new { name = actionName }) },
		},
		WithVariablesInReturn = true,
	});

	var processResultJson = camundaResult.Variables["result"]?.Value as string;
	var result = JsonSerializer.Deserialize<Result>(processResultJson, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
	return result;
}

When MaxDegreeOfParallelism is bigger than 1, I get all kinds of unexpected errors, like:

  • java.lang.NullPointerException
  • org.camunda.bpm.engine.ProcessEngineException: ENGINE-17004 Cannot add variable instance with name result. Variable already exists'
  • java.lang.NullPointerException: Cannot invoke "org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity.getParentActivityInstanceId()" because "scopeExecution" is null

Any idea why this happens and what I can do to fix it?

Here are some stack traces (they were too long to post here):