elsa-workflows/elsa-core · error · JsonException
Failed to parse JsonDocument
Error message
Failed to parse JsonDocument
What it means
Thrown in ConnectionJsonConverter.Read when JsonDocument.TryParseValue cannot parse the incoming token into a JsonDocument while deserializing a Flowchart Connection. It signals malformed JSON, not a missing field. Thrown during workflow definition deserialization.
Solutions
- Validate the workflow definition JSON with JsonDocument.Parse before deserialization.
- Check the JSON source (DB column, file, HTTP body) for truncation or encoding corruption.
- Ensure each connection is a JSON object like {"source":..., "target":...}, not a string or array.
- Wrap deserialization in try/catch for JsonException and log the raw JSON fragment to locate the corrupt element.
Example fix
// before
var connection = JsonSerializer.Deserialize<Connection>(badJson); // throws JsonException
// after
try { var connection = JsonSerializer.Deserialize<Connection>(json); }
catch (JsonException ex) { logger.LogError(ex, "Invalid connection JSON: {Json}", json); } Defensive patterns
Strategy: try-catch
Validate before calling
using var doc = JsonDocument.Parse(json); // throws early with position info if malformed
Type guard
static bool IsValidJson(string json) { try { using var _ = JsonDocument.Parse(json); return true; } catch (JsonException) { return false; } } Try / catch
try { var connection = JsonSerializer.Deserialize<Connection>(json); }
catch (JsonException ex)
{
logger.LogError(ex, "Failed to deserialize Connection: {Message}", ex.Message);
} Prevention
- Validate stored workflow definition JSON after export/import round-trips.
- Avoid hand-editing workflow JSON; use the designer or API.
- Check DB columns/HTTP bodies for truncation before deserialization.
When it happens
Trigger: Deserializing workflow definitions where the JSON for a Connection element is syntactically invalid — truncated JSON, a bare string, or a non-object token where a connection object was expected.
Common situations: Corrupted workflow definition JSON stored in a database or file; hand-edited JSON; middleware that mangles the payload; truncated HTTP bodies.
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
- Failed to parse JsonDocument
- Missing property ' ' or
- Failed to parse JsonDocument
- Cannot deserialize to .
- Failed to deserialize
AI-assisted analysis of elsa-workflows/elsa-core@fe9217bdfa (2026-09-13).
Data as JSON: /api/errors/504ffbaea0e05491.
Report an issue: GitHub.
Appendix: source
Thrown at src/modules/Elsa.Workflows.Core/Activities/Flowchart/Serialization/ConnectionJsonConverter.cs:22
using Microsoft.Extensions.Logging;
namespace Elsa.Workflows.Activities.Flowchart.Serialization;
/// <summary>
/// Converts <see cref="Connection"/> to and from JSON.
/// </summary>
public class ConnectionJsonConverter(IDictionary<string, IActivity> activities, ILoggerFactory loggerFactory) : JsonConverter<Connection?>
{
private readonly ILogger _logger = loggerFactory.CreateLogger<ConnectionJsonConverter>();
/// <inheritdoc />
public override bool CanConvert(Type typeToConvert) => typeToConvert == typeof(Connection);
/// <inheritdoc />
public override Connection? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (!JsonDocument.TryParseValue(ref reader, out var doc))
throw new JsonException("Failed to parse JsonDocument");
var root = doc.RootElement;
// case‐insensitive get
JsonElement Get(string name)
{
if (root.TryGetProperty(name, out var e))
return e;
var alt = char.ToUpperInvariant(name[0]) + name.Substring(1);
if (root.TryGetProperty(alt, out e))
return e;
throw new JsonException($"Missing property '{name}' or '{alt}'");
}
var sourceElement = Get("source");
var targetElement = Get("target");
// now inside sourceElement and targetElement, their childrenView on GitHub (pinned to fe9217bdfa)