elsa-workflows/elsa-core · error · JsonException
Missing property ' ' or
Error message
Missing property '{name}' or '{alt}' What it means
Thrown by ConnectionJsonConverter.Read when the connection JSON object contains neither the lowercase nor PascalCase form of a required property ('source'/'Source', 'target'/'Target'). The converter's Get helper tries both spellings before failing. It means the connection payload is structurally incomplete.
Solutions
- Ensure each connection object has both 'source' and 'target' properties.
- If your producer uses different key names, rename them to source/target before deserialization or write a custom converter.
- Inspect the offending JSON object to confirm which property is missing.
- Validate workflow definitions against the expected connection schema before ingestion.
Example fix
// before
{"connections": [{"source": {"activity":"a"}}]} // missing target
// after
{"connections": [{"source": {"activity":"a"}, "target": {"activity":"b"}}]} Defensive patterns
Strategy: validation
Validate before calling
using var doc = JsonDocument.Parse(json);
foreach (var conn in doc.RootElement.GetProperty("connections").EnumerateArray())
{
if (!conn.TryGetProperty("source", out _) || !conn.TryGetProperty("target", out _))
throw new ArgumentException("Each connection must contain 'source' and 'target'.");
} Type guard
static bool HasConnectionEndpoints(JsonElement conn) =>
conn.ValueKind == JsonValueKind.Object && conn.TryGetProperty("source", out _) && conn.TryGetProperty("target", out _); Try / catch
try { var flowchart = JsonSerializer.Deserialize<Activities.Flowchart>(json); }
catch (JsonException ex) when (ex.Message.StartsWith("Missing property"))
{
logger.LogError(ex, "Connection JSON is missing source/target: {Message}", ex.Message);
} Prevention
- Ensure connection producers emit both 'source' and 'target' keys.
- Validate external tool exports against the Elsa connection schema before import.
- Rename 'from'/'to' style keys to source/target before deserialization.
When it happens
Trigger: Deserializing a Connection whose JSON object lacks 'source' or 'target' keys (or their capitalized variants), e.g. an object with only a source or with entirely different key names.
Common situations: Hand-authored workflow JSON missing one endpoint; external tools exporting connections with different property names (e.g. 'from'/'to'); API clients posting partial connection objects.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Failed to parse JsonDocument
- Failed to parse JsonDocument
- The serialization type alias is missing.
- Unsupported console stream value
- The persisted external authentication value could not be…
AI-assisted analysis of elsa-workflows/elsa-core@fe9217bdfa (2026-09-13).
Data as JSON: /api/errors/47a81039699946f3.
Report an issue: GitHub.
Appendix: source
Thrown at src/modules/Elsa.Workflows.Core/Activities/Flowchart/Serialization/ConnectionJsonConverter.cs:34
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 children
// are again PascalCased (“Activity”, “Port”), so do the same thing:
string GetId(JsonElement container, string propName)
{
if (container.TryGetProperty(propName, out var p))
return p.GetString()!;
var alt = char.ToUpperInvariant(propName[0]) + propName.Substring(1);
return container.GetProperty(alt).GetString()!;
}
string? GetPort(JsonElement container, string propName)
{View on GitHub (pinned to fe9217bdfa)