Merge pull request #7711 from elsa-workflows/codex/7708-notfoundactivity-guard

[codex] Guard missing NotFoundActivity descriptor during deserialization
This commit is contained in:
Sipke Schoorstra 2026-06-14 22:33:41 +02:00 committed by GitHub
commit 04d602fcd2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 28 additions and 7 deletions

View file

@ -49,7 +49,11 @@ public class ActivityJsonConverter(
// If the activity type is not found, create a NotFoundActivity instead.
if (activityDescriptor == null)
{
var notFoundActivityDescriptor = activityRegistry.Find<NotFoundActivity>()!;
var notFoundActivityDescriptor = activityRegistry.Find<NotFoundActivity>();
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<NotFoundActivity>(notFoundActivityDescriptor, activityRoot, clonedOptions);
LogExceptionsIfAny(notFoundActivityResult);
@ -186,4 +190,4 @@ public class ActivityJsonConverter(
clonedOptions.Converters.Add(new JsonIgnoreCompositeRootConverterFactory(serviceProvider.GetRequiredService<ActivityWriter>()));
return clonedOptions;
}
}
}

View file

@ -48,11 +48,7 @@ public sealed class ActivityJsonConverterTests
public void When_DeserializeUnknownActivity_Then_ReturnsNotFoundActivity()
{
// Arrange
var activityRegistry = Substitute.For<IActivityRegistry>();
activityRegistry
.Find(NotFoundActivityTypeName)
.Returns(new ActivityDescriptor());
var activityRegistry = CreateUnknownActivityRegistry(new ActivityDescriptor());
var sut = CreateSut(activityRegistry);
// Act
@ -92,6 +88,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<InvalidOperationException>(() => 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()
{
@ -164,6 +174,13 @@ public sealed class ActivityJsonConverterTests
return activityRegistry;
}
static IActivityRegistry CreateUnknownActivityRegistry(ActivityDescriptor? notFoundActivityDescriptor = null)
{
var activityRegistry = Substitute.For<IActivityRegistry>();
activityRegistry.Find(NotFoundActivityTypeName).Returns(notFoundActivityDescriptor);
return activityRegistry;
}
static IActivityRegistry CreateActivityRegistry_FindByCustomProperty(string customPropertyName, string customPropertyValue)
{
var descriptor = new ActivityDescriptor