elsa-workflows/elsa-core · error · JsonException
Failed to parse JsonDocument
Error message
Failed to parse JsonDocument
What it means
ActivityJsonConverter.Read converts incoming JSON into an IActivity. It first parses the JSON token into a JsonDocument; if TryParseValue fails (malformed or unexpected JSON), it throws this JsonException. It is a low-level guard ensuring only valid JSON objects are processed for activity deserialization.
Solutions
- Validate/pretty-check the JSON source with a parser before handing it to Elsa's serializer.
- Fix malformed JSON (missing braces/commas, truncation) at the source of the string.
- Ensure you deserialize with System.Text.Json options compatible with the payload (e.g. no embedded comments unless configured).
- If data comes from storage, re-export the workflow definition to regenerate clean JSON.
Example fix
// before var activity = JsonSerializer.Deserialize<IActivity>(truncatedJson); // after using var doc = JsonDocument.Parse(json); // throws a precise line/position error first var activity = JsonSerializer.Deserialize<IActivity>(json);
Defensive patterns
Strategy: validation
Validate before calling
try { using var _ = JsonDocument.Parse(json); } catch (JsonException ex) { throw new InvalidOperationException("Workflow JSON is malformed", ex); }
var activity = JsonSerializer.Deserialize<IActivity>(json, options); Type guard
static bool IsValidJson(string s) { try { using var d = JsonDocument.Parse(s); return true; } catch (JsonException) { return false; } } Try / catch
try { var activity = JsonSerializer.Deserialize<IActivity>(json); } catch (JsonException ex) when (ex.Message.Contains("Failed to parse JsonDocument")) { log.LogError(ex, "Malformed activity JSON"); /* repair or re-export payload */ } Prevention
- Round-trip workflow JSON through Elsa export rather than hand-editing
- Validate JSON files in CI before deploying workflow definitions
- Check transport/storage for truncation (body size limits, blob column sizes)
When it happens
Trigger: Deserializing workflow/activity JSON where the Utf8JsonReader is not positioned on a valid JSON value (truncated JSON, invalid syntax, or reading a primitive where a document is required) at ActivityJsonConverter.Read (src/modules/Elsa.Workflows.Core/Serialization/Converters/ActivityJsonConverter.cs:28).
Common situations: Passing hand-edited workflow JSON from files or database blobs that got corrupted; copying JSON with trailing commas or comments; deserializing a partial HTTP response body.
Understand the failure class
Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Runtime entity definition document
- Runtime entity instance document
- Failed to extract activity type property
- Unknown token
- Expected start of object.
AI-assisted analysis of elsa-workflows/elsa-core@fe9217bdfa (2026-09-13).
Data as JSON: /api/errors/1d6f83732cb800b4.
Report an issue: GitHub.
Appendix: source
Thrown at src/modules/Elsa.Workflows.Core/Serialization/Converters/ActivityJsonConverter.cs:28
using Microsoft.Extensions.Logging;
namespace Elsa.Workflows.Serialization.Converters;
/// <summary>
/// (De)serializes objects of type <see cref="IActivity"/>.
/// </summary>
public class ActivityJsonConverter(
IActivityRegistry activityRegistry,
IExpressionDescriptorRegistry expressionDescriptorRegistry,
ActivityWriter activityWriter,
IServiceProvider serviceProvider)
: JsonConverter<IActivity>
{
/// <inheritdoc />
public override IActivity Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (!JsonDocument.TryParseValue(ref reader, out var doc))
throw new JsonException("Failed to parse JsonDocument");
var activityRoot = doc.RootElement;
var activityTypeName = GetActivityDetails(activityRoot, out var activityTypeVersion, out var activityDescriptor);
var notFoundActivityTypeName = ActivityTypeNameHelper.GenerateTypeName<NotFoundActivity>();
// If the activity type is a NotFoundActivity, try to extract the original activity type name and version.
if (activityTypeName.Equals(notFoundActivityTypeName) && activityRoot.TryGetProperty("originalActivityJson", out var originalActivityJson))
{
activityRoot = JsonDocument.Parse(originalActivityJson.GetString()!).RootElement;
activityTypeName = GetActivityDetails(activityRoot, out activityTypeVersion, out activityDescriptor);
}
var clonedOptions = GetClonedOptions(options);
// If the activity type is not found, create a NotFoundActivity instead.
if (activityDescriptor == null)
{
var notFoundActivityDescriptor = activityRegistry.Find<NotFoundActivity>()!;
var notFoundActivityResult = JsonActivityConstructorContextHelper.CreateActivity<NotFoundActivity>(notFoundActivityDescriptor, activityRoot, clonedOptions);View on GitHub (pinned to fe9217bdfa)