elsa-workflows/elsa-core · error · JsonException

Expected a PropertyName token

Error message

Expected a PropertyName token

What it means

While iterating the JSON object, HttpHeadersConverter expects each member to be a property name (a header key). If it encounters a token other than EndObject or PropertyName at the member position, it throws JsonException('Expected a PropertyName token'), guarding against structurally invalid header objects.

Solutions

  1. Repair the JSON so it is a well-formed object of key->string-or-string[] pairs
  2. Re-serialize the headers through HttpHeaders itself instead of hand-writing JSON
  3. Validate with JsonDocument.Parse before deserializing into HttpHeaders
  4. If state is persisted, isolate and delete/repair the corrupt instance state record

Example fix

// before
{"Accept"} // invalid: missing value, breaks at member position
// after
{"Accept": ["text/plain"]}
Defensive patterns

Strategy: type-guard

Validate before calling

using var doc = JsonDocument.Parse(json);
foreach (var prop in doc.RootElement.EnumerateObject())
    if (prop.Value.ValueKind is not (JsonValueKind.String or JsonValueKind.Array))
        throw new FormatException($"Header '{prop.Name}' has invalid value kind {prop.Value.ValueKind}");

Type guard

bool IsValidHeadersObject(JsonElement e) => e.ValueKind == JsonValueKind.Object && e.EnumerateObject().All(p => p.Value.ValueKind is JsonValueKind.String or JsonValueKind.Array);

Try / catch

try { headers = JsonSerializer.Deserialize<HttpHeaders>(json, options); }
catch (JsonException ex)
{
    logger.LogWarning(ex, "Headers JSON is not a valid key/value object");
    throw new InvalidDataException("Invalid HttpHeaders payload", ex);
}

Prevention

When it happens

Trigger: Deserializing HttpHeaders from malformed JSON such as a nested array element or a bare value inside the object where a key should be, e.g. {"Accept"} or nested objects without keys — typically corrupt or hand-crafted persisted state.

Common situations: Corrupted workflow instance state in a durable store; custom code writing headers with the wrong serializer; JSON produced by another language/library that doesn't map header objects cleanly.

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.

Related errors


AI-assisted analysis of elsa-workflows/elsa-core@fe9217bdfa (2026-09-13). Data as JSON: /api/errors/e7f6823138af5760. Report an issue: GitHub.

Appendix: source

Thrown at src/modules/Elsa.Http/Serialization/HttpHeadersConverter.cs:25

/// A custom JSON converter for HttpHeaders that supports both single and multiple values.
/// </summary>
public class HttpHeadersConverter : JsonConverter<HttpHeaders>
{
    /// <inheritdoc />
    public override HttpHeaders Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        if (reader.TokenType != JsonTokenType.StartObject)
            throw new JsonException("Expected StartObject token");

        var headers = new HttpHeaders();

        while (reader.Read())
        {
            if (reader.TokenType == JsonTokenType.EndObject)
                return headers;

            if (reader.TokenType != JsonTokenType.PropertyName)
                throw new JsonException("Expected a PropertyName token");

            var key = reader.GetString()!;
            reader.Read();

            // If the next token is not a StartArray token, then we expect a String token.
            switch (reader.TokenType)
            {
                case JsonTokenType.StartArray:
                {
                    var values = new List<string>();
                    while (reader.Read() && reader.TokenType != JsonTokenType.EndArray) values.Add(reader.GetString()!);
                    headers.Add(key, values.ToArray());
                    break;
                }
                case JsonTokenType.String:
                {
                    var singleValue = reader.GetString()!;
                    headers.Add(key, new[] { singleValue });

View on GitHub (pinned to fe9217bdfa)