From a5a3aa77ae6b6a4f0229f9157626a84ebaa25d55 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Tue, 9 Jun 2026 21:28:27 +0200 Subject: [PATCH 1/3] Guard missing NotFoundActivity descriptor during deserialization --- .../Serialization/Converters/ActivityJsonConverter.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/modules/Elsa.Workflows.Core/Serialization/Converters/ActivityJsonConverter.cs b/src/modules/Elsa.Workflows.Core/Serialization/Converters/ActivityJsonConverter.cs index 29da39c2f..46627c507 100644 --- a/src/modules/Elsa.Workflows.Core/Serialization/Converters/ActivityJsonConverter.cs +++ b/src/modules/Elsa.Workflows.Core/Serialization/Converters/ActivityJsonConverter.cs @@ -42,7 +42,11 @@ public class ActivityJsonConverter( // If the activity type is not found, create a NotFoundActivity instead. if (activityDescriptor == null) { - var notFoundActivityDescriptor = activityRegistry.Find()!; + var notFoundActivityDescriptor = activityRegistry.Find(); + + if (notFoundActivityDescriptor == null) + throw new InvalidOperationException($"Unable to deserialize activity type '{activityTypeName}' because the NotFoundActivity descriptor is not registered. Ensure the activity registry has been populated before deserializing workflows."); + var notFoundActivityResult = JsonActivityConstructorContextHelper.CreateActivity(notFoundActivityDescriptor, activityRoot, clonedOptions); LogExceptionsIfAny(notFoundActivityResult); From 42ef838323d95b75f5b444f241be8f862f1fdd92 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Tue, 9 Jun 2026 21:28:29 +0200 Subject: [PATCH 2/3] Add regression test for missing NotFoundActivity descriptor --- .../Converters/ActivityJsonConverterTests.cs | 29 +++++++++++++++---- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/test/unit/Elsa.Workflows.Core.UnitTests/Serialization/Converters/ActivityJsonConverterTests.cs b/test/unit/Elsa.Workflows.Core.UnitTests/Serialization/Converters/ActivityJsonConverterTests.cs index 7782aeb13..9ce562df4 100644 --- a/test/unit/Elsa.Workflows.Core.UnitTests/Serialization/Converters/ActivityJsonConverterTests.cs +++ b/test/unit/Elsa.Workflows.Core.UnitTests/Serialization/Converters/ActivityJsonConverterTests.cs @@ -48,11 +48,7 @@ public sealed class ActivityJsonConverterTests public void When_DeserializeUnknownActivity_Then_ReturnsNotFoundActivity() { // Arrange - var activityRegistry = Substitute.For(); - activityRegistry - .Find(NotFoundActivityTypeName) - .Returns(new ActivityDescriptor()); - + var activityRegistry = CreateUnknownActivityRegistry(new ActivityDescriptor()); var sut = CreateSut(activityRegistry); // Act @@ -71,6 +67,20 @@ public sealed class ActivityJsonConverterTests Assert.True(notFoundActivity.Metadata.ContainsKey("description")); } + [Fact] + public void When_DeserializeUnknownActivity_And_NotFoundActivityDescriptorMissing_Then_ThrowsClearException() + { + // Arrange + var activityRegistry = CreateUnknownActivityRegistry(); + var sut = CreateSut(activityRegistry); + + // Act + var exception = Assert.Throws(() => Execute(sut, UnknownActivityJson)); + + // Assert + Assert.Equal($"Unable to deserialize activity type '{UnknownActivityTypeName}' because the NotFoundActivity descriptor is not registered. Ensure the activity registry has been populated before deserializing workflows.", exception.Message); + } + [Fact] public void When_DeserializeWorkflowAsActivity_And_WorkflowDefinitionIdSpecified_Then_FindsAndInstantiatesActivity() { @@ -136,6 +146,13 @@ public sealed class ActivityJsonConverterTests return activityRegistry; } + static IActivityRegistry CreateUnknownActivityRegistry(ActivityDescriptor? notFoundActivityDescriptor = null) + { + var activityRegistry = Substitute.For(); + activityRegistry.Find(NotFoundActivityTypeName).Returns(notFoundActivityDescriptor); + return activityRegistry; + } + static IActivityRegistry CreateActivityRegistry_FindByCustomProperty(string customPropertyName, string customPropertyValue) { var descriptor = new ActivityDescriptor @@ -352,4 +369,4 @@ public sealed class ActivityJsonConverterTests } private static ILogger CreateLogger() => LoggerFactory.Create(_ => { }).CreateLogger(); -} +} \ No newline at end of file From 0d7c8106887c43db0717f3f2eab740f2c023e174 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Sun, 14 Jun 2026 19:07:15 +0200 Subject: [PATCH 3/3] address greptile review feedback --- .../Serialization/Converters/ActivityJsonConverterTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/Elsa.Workflows.Core.UnitTests/Serialization/Converters/ActivityJsonConverterTests.cs b/test/unit/Elsa.Workflows.Core.UnitTests/Serialization/Converters/ActivityJsonConverterTests.cs index 9ce562df4..08e8ce0ec 100644 --- a/test/unit/Elsa.Workflows.Core.UnitTests/Serialization/Converters/ActivityJsonConverterTests.cs +++ b/test/unit/Elsa.Workflows.Core.UnitTests/Serialization/Converters/ActivityJsonConverterTests.cs @@ -369,4 +369,4 @@ public sealed class ActivityJsonConverterTests } private static ILogger CreateLogger() => LoggerFactory.Create(_ => { }).CreateLogger(); -} \ No newline at end of file +}