elsa-workflows / elsa-workflows/elsa-core
[BUG] Fork throws exception when deserializing Completed property with previous activity name.
- Dominant language
- C#
- Stars
- 7.9k
- Forks
- 1.5k
- Avg merge
- 15h 22m
- Merged PRs (30d)
- 114
Description
## Description
I have two approval activities in a Fork activity. When I complete the second activity, the following code fails in Fork.cs
Fork.cs
Line 65
```
// Append activity to set of completed activities.
var completedActivityIds = targetContext.UpdateProperty>("Completed", set =>
{
set ??= new HashSet();
set.Add(completedChildActivityId);
return set;
});
```
The first approval activity correctly serializes the activity name and saves it to Completed property.
On completion, the second approval activity fails because it can't deserialize the Completed property before adding its own name
Exception
```
Elsa.Expressions.Exceptions.TypeConversionException: Failed to deserialize {"$values":["CreateApprovalTask1"],"_type":"String[]"} to System.Collections.Generic.HashSet`1[System.String]
---> System.Text.Json.JsonException: A '$values' metadata property must always be preceded by other metadata properties, such as '$id' or '$type'. Path: $.$values | LineNumber: 0 | BytePositionInLine: 11.
```
## Steps to Reproduce
Create a FlowChart workflow with 2 approval tasks (activity with bookmark) in a Fork
Resume workflow at first bookmark - works
Resume workflow at second bookmark - error
```
var options = new ResumeWorkflowRuntimeParams()
{
BookmarkId = task.BookmarkId,
};
await workflowRuntime.ResumeWorkflowAsync(task.WorkflowInstanceId, options);
```
Abbreviated worklow
```
List roles = ["testrole1", "testrole2"];
ICollection approvalActivities = new List();
foreach (var role in roles)
{
approvalActivities.Add(
new CreateApprovalTask
{
ApprovalId = new Input(context => approvalId.Get(context)),
UserName = new Input(context => userName.Get(context)!),
DisplayName = new Input(context => displayName.Get(context)!),
Name = $"CreateApprovalTask{role}"
}
);
}
var forkApproval = new Fork
{
JoinMode = ForkJoinMode.WaitAll,
Branches = approvalActivities
};
var approvalCompleteWrite = new WriteLine("Approval Complete");
var end = new WriteLine("End Material Approval");
builder.Root = new Flowchart
{
Start = start,
Activities =
{
start,
createMaterialApproval,
forkApproval,
approvalCompleteWrite,
end
},
Connections =
{
new Connection(start, createMaterialApproval),
new Connection(createMaterialApproval, correlate),
new Connection(correlate, forkApproval),
new Connection(forkApproval, approvalCompleteWrite),
new Connection(approvalCompleteWrite, end),
}
};
```
3. **Attachments**:
Flowchart state after first approval
```
{
"$id": "30",
"id": "4518b244420f23c4",
"parentContextId": "62ca75922c46a783",
"scheduledActivityNodeId": "Workflow1:Flowchart1:Fork1",
"ownerActivityNodeId": "Workflow1:Flowchart1",
"properties": {
"$id": "31",
"Completed": {
"$id": "32",
"$values": [
"CreateApprovalTask1"
],
"_type": "String[]"
}
},
"activityState": {
"$id": "33",
"JoinMode": "WaitAll"
},
"dynamicVariables": {
"$id": "34",
"$values": []
},
"status": "Running",
"startedAt": "2024-10-04T09:54:16.2750808+00:00"
},
```
Flowchart state after second approval and exception
```
,
{
"$id": "16",
"id": "4518b244420f23c4",
"parentContextId": "62ca75922c46a783",
"scheduledActivityNodeId": "Workflow1:Flowchart1:Fork1",
"ownerActivityNodeId": "Workflow1:Flowchart1",
"properties": {
"$id": "17",
"Completed": {
"\\\\$values": {
"$id": "18",
"$values": [
"CreateApprovalTask1"
],
"_type": "Object[]"
}
}
},
"activityState": {
"$id": "19",
"JoinMode": "WaitAll"
},
"dynamicVariables": {
"$id": "20",
"$values": []
},
"status": "Running",
"startedAt": "2024-10-04T09:54:16.2750808+00:00"
}
```
4. **Reproduction Rate**: Indicate how often the bug occurs when following these steps (e.g., "every time", "intermittently: about 50% of the time").
5.
every time
## Environment
## Log Output
An exception was caught from a downstream middleware component
Elsa.Expressions.Exceptions.TypeConversionException: Failed to deserialize {"$values":["CreateApprovalTask1"],"_type":"String[]"} to System.Collections.Generic.HashSet`1[System.String]
---> System.Text.Json.JsonException: A '$values' metadata property must always be preceded by other metadata properties, such as '$id' or '$type'. Path: $.$values | LineNumber: 0 | BytePositionInLine: 11.
at System.Text.Json.ThrowHelper.ThrowJsonException(String message)
at System.Text.Json.ThrowHelper.ThrowJsonException_MetadataStandaloneValuesProperty(ReadStack& state, ReadOnlySpan`1 propertyName)
at System.Text.Json.JsonSerializer.TryReadMetadata(JsonConverter converter, JsonTypeInfo jsonTypeInfo, Utf8JsonReader& reader, ReadStack& state)
at System.Text.Json.Serialization.JsonCollectionConverter`2.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, TCollection& value)
at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value, Boolean& isPopulatedValue)
at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1.DeserializeAsObject(Utf8JsonReader& reader, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadFromSpanAsObject(ReadOnlySpan`1 utf8Json, JsonTypeInfo jsonTypeInfo, Nullable`1 actualByteCount)
at System.Text.Json.JsonSerializer.ReadFromSpanAsObject(ReadOnlySpan`1 json, JsonTypeInfo jsonTypeInfo)
at Elsa.Expressions.Helpers.ObjectConverter.ConvertTo(Object value, Type targetType, ObjectConverterOptions converterOptions)
--- End of inner exception stack trace ---
at Elsa.Expressions.Helpers.ObjectConverter.ConvertTo(Object value, Type targetType, ObjectConverterOptions converterOptions)
at Elsa.Expressions.Helpers.ObjectConverter.ConvertTo(Object value, Type targetType, ObjectConverterOptions converterOptions)
at Elsa.Expressions.Helpers.ObjectConverter.ConvertTo[T](Object value, ObjectConverterOptions converterOptions)
at Elsa.Extensions.DictionaryExtensions.TryGetValue[TKey,T](IDictionary`2 dictionary, TKey key, T& value)
at Elsa.Workflows.ActivityExecutionContext.GetProperty[T](String key)
at Elsa.Workflows.ActivityExecutionContext.UpdateProperty[T](String key, Func`2 updater)
at Elsa.Workflows.Activities.Fork.CompleteChildAsync(ActivityCompletedContext context)
at Elsa.Workflows.Behaviors.ScheduledChildCallbackBehavior.OnActivityCompletedAsync(ActivityCompleted signal, SignalContext context)
at Elsa.Workflows.Behavior.Elsa.Workflows.Contracts.ISignalHandler.ReceiveSignalAsync(Object signal, SignalContext context)
at Elsa.Workflows.Activity.Elsa.Workflows.Contracts.ISignalHandler.ReceiveSignalAsync(Object signal, SignalContext context)
at Elsa.Extensions.ActivityExecutionContextExtensions.SendSignalAsync(ActivityExecutionContext context, Object signal)
at Elsa.Workflows.ActivityExecutionContext.CompleteActivityAsync(Object result)
at Workflow.Services.Workflows.Activities.CreateApprovalTask.CompleteActivityAsync(ActivityExecutionContext context) in D:\work\biocats\Workflow\Workflow.Services\Workflows\Elsa\Activities\CreateApprovalTask.cs:line 83
at Elsa.Workflows.Middleware.Activities.DefaultActivityInvokerMiddleware.ExecuteActivityAsync(ActivityExecutionContext context)
at Elsa.Workflows.Runtime.Middleware.Activities.BackgroundActivityInvokerMiddleware.ExecuteActivityAsync(ActivityExecutionContext context)
at Elsa.Workflows.Middleware.Activities.DefaultActivityInvokerMiddleware.InvokeAsync(ActivityExecutionContext context)
at Elsa.Workflows.Middleware.Activities.NotificationPublishingMiddleware.InvokeAsync(ActivityExecutionContext context)
at Elsa.Workflows.Middleware.Activities.ExecutionLogMiddleware.InvokeAsync(ActivityExecutionContext context)
at Elsa.Workflows.Middleware.Activities.ExceptionHandlingMiddleware.InvokeAsync(ActivityExecutionContext context)
## Troubleshooting Attempts
Describe any steps you have taken to troubleshoot or resolve the issue yourself.
## Additional Context
Add any other context about the problem here. This could include the frequency of the issue (e.g., intermittent, every time), conditions under which the issue appears, etc.
## Related Issues
Link to any related issues here.
Contributor guide
Assessment
This issue has not been assessed yet.