{"record":{"id":"c89508235475c4ca","repo":"elsa-workflows/elsa-core","slug":"expected-start-of-object","errorCode":null,"errorMessage":"Expected start of object.","messagePattern":"Expected start of object\\.","errorType":"exception","errorClass":"JsonException","httpStatus":null,"severity":"error","filePath":"src/modules/Elsa.Workflows.Core/Serialization/Converters/PolymorphicDictionaryConverter.cs","lineNumber":25,"sourceCode":"/// <summary>\n/// A converter that can convert a dictionary of string keys and object values while preserving the object type.\n/// </summary>\npublic class PolymorphicDictionaryConverter : JsonConverter<IDictionary<string, object>>\n{\n    private readonly JsonConverter<object> _objectConverter;\n\n    /// <inheritdoc />\n    public PolymorphicDictionaryConverter(JsonSerializerOptions options, ISerializationTypeRegistry workflowJsonTypeRegistry)\n    {\n        var factory = (JsonConverterFactory)(options.Converters.FirstOrDefault(x => x is PolymorphicObjectConverterFactory) ?? new PolymorphicObjectConverterFactory(workflowJsonTypeRegistry));\n        _objectConverter = (JsonConverter<object>)factory.CreateConverter(typeof(object), options)!;\n    }\n\n    /// <inheritdoc />\n    public override IDictionary<string, object> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n    {\n        if (reader.TokenType != JsonTokenType.StartObject)\n            throw new JsonException(\"Expected start of object.\");\n\n        var dictionary = new Dictionary<string, object>();\n\n        while (reader.Read())\n        {\n            if (reader.TokenType == JsonTokenType.EndObject)\n                return dictionary;\n\n            var key = reader.GetString()!;\n            reader.Read();\n            var value = _objectConverter.Read(ref reader, typeof(object), options)!;\n            dictionary.Add(key, value);\n        }\n\n        throw new JsonException(\"Expected end of object.\");\n    }\n\n    /// <inheritdoc />","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/elsa-workflows/elsa-core/blob/fe9217bdfa0e27f0e09e45006eb6898f616e513d/src/modules/Elsa.Workflows.Core/Serialization/Converters/PolymorphicDictionaryConverter.cs#L7-L43","documentation":"PolymorphicDictionaryConverter.Read deserializes JSON objects into IDictionary<string,object> with polymorphic values. It requires the current token to be JsonTokenType.StartObject; otherwise it throws JsonException(\"Expected start of object.\"). This guards the contract that dictionary targets must map to JSON objects.","triggerScenarios":"Deserializing a field declared as IDictionary<string,object> (or a dictionary-like property) whose JSON value is an array, string, number, or null instead of an object (src/modules/Elsa.Workflows.Core/Serialization/Converters/PolymorphicDictionaryConverter.cs:25).","commonSituations":"Workflow state where a dictionary property was previously stored as a JSON array and the model changed; hand-written JSON for variables/settings using wrong shape; API clients posting arrays where objects are expected.","solutions":["Fix the JSON payload so the dictionary field is a JSON object (key/value pairs).","Change the property type to match the actual payload shape if arrays are legitimate.","Validate the payload shape before deserialization.","Migrate legacy stored state data to the object shape expected by the current model."],"exampleFix":"// before\nvar d = JsonSerializer.Deserialize<IDictionary<string, object>>(\"[1,2,3]\");\n\n// after\nvar d = JsonSerializer.Deserialize<IDictionary<string, object>>(\"{\\\"a\\\":1}\");","handlingStrategy":"validation","validationCode":"using var doc = JsonDocument.Parse(json);\nif (doc.RootElement.ValueKind != JsonValueKind.Object)\n    throw new InvalidOperationException(\"Expected a JSON object for dictionary deserialization\");","typeGuard":"static bool IsJsonObjectString(string s) { try { using var d = JsonDocument.Parse(s); return d.RootElement.ValueKind == JsonValueKind.Object; } catch { return false; } }","tryCatchPattern":"try { var d = JsonSerializer.Deserialize<IDictionary<string, object>>(json); } catch (JsonException ex) when (ex.Message == \"Expected start of object.\") { log.LogError(ex, \"Dictionary payload is not a JSON object\"); }","preventionTips":["Ensure dictionary-typed fields are always serialized as JSON objects","Migrate legacy array-shaped state data before upgrading","Validate request payloads at the API boundary before deserializing into dictionaries"],"tags":["csharp","json","serialization","dictionary"],"backgroundTag":"type-mismatch","analyzedSha":"fe9217bdfa0e27f0e09e45006eb6898f616e513d","analyzedAt":"2026-09-13T20:32:34.702Z","contentChangedAt":"2026-09-13T20:32:34.702Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}