{"record":{"id":"5ae1afcca9607a94","repo":"elsa-workflows/elsa-core","slug":"the-platform-shell-overlay-file-must-contain-a-json-object","errorCode":null,"errorMessage":"The Platform shell overlay file must contain a JSON object.","messagePattern":"The Platform shell overlay file must contain a JSON object\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/modules/Elsa.Platform.Integration/Services/FileShellConfigurationOverlayStore.cs","lineNumber":82,"sourceCode":"                Merge(configuration, settingsObject);\n\n            return await SaveIfChangedAsync(root, before, cancellationToken);\n        }\n        finally\n        {\n            _semaphore.Release();\n        }\n    }\n\n    private async Task<JsonObject> LoadAsync(CancellationToken cancellationToken)\n    {\n        var path = GetPath();\n        if (!File.Exists(path))\n            return new JsonObject();\n\n        await using var stream = File.OpenRead(path);\n        return await JsonNode.ParseAsync(stream, cancellationToken: cancellationToken) as JsonObject\n            ?? throw new InvalidOperationException(\"The Platform shell overlay file must contain a JSON object.\");\n    }\n\n    private async Task<bool> SaveIfChangedAsync(JsonObject root, string before, CancellationToken cancellationToken)\n    {\n        var after = Serialize(root);\n        if (string.Equals(before, after, StringComparison.Ordinal))\n            return false;\n\n        var path = GetPath();\n        var directory = Path.GetDirectoryName(path);\n        if (!string.IsNullOrWhiteSpace(directory))\n            Directory.CreateDirectory(directory);\n\n        var tempPath = $\"{path}.{Guid.NewGuid():N}.tmp\";\n        await File.WriteAllTextAsync(tempPath, after, cancellationToken);\n        File.Move(tempPath, path, overwrite: true);\n        return true;\n    }","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/elsa-workflows/elsa-core/blob/fe9217bdfa0e27f0e09e45006eb6898f616e513d/src/modules/Elsa.Platform.Integration/Services/FileShellConfigurationOverlayStore.cs#L64-L100","documentation":"FileShellConfigurationOverlayStore.LoadAsync reads the shell overlay file and parses it with JsonNode.ParseAsync, then casts to JsonObject. If the file's top-level JSON value is not an object (e.g. an array, string, or number), the cast fails and this InvalidOperationException is thrown.","triggerScenarios":"The file at ShellOverlayPath exists and contains valid JSON whose root is not an object — for example '[ ]' or '\"text\"' — and LoadAsync is invoked during overlay load.","commonSituations":"A user hand-edited the overlay file into an array; an export tool wrote a different JSON shape; the file was overwritten by another process with the wrong schema.","solutions":["Edit the overlay file so its root is a JSON object, e.g. { }. Validate with a JSON parser.","Delete or rename the malformed file; LoadAsync recreates an empty JsonObject when the file is absent.","Restore the file from backup or regenerate it by re-saving the overlay through the integration."],"exampleFix":"// before (shell-overlay.json)\n[]\n// after (shell-overlay.json)\n{}","handlingStrategy":"try-catch","validationCode":"using var doc = JsonDocument.Parse(await File.ReadAllTextAsync(overlayPath));\nif (doc.RootElement.ValueKind != JsonValueKind.Object)\n    throw new InvalidOperationException(\"Overlay file root must be a JSON object.\");","typeGuard":"bool IsValidOverlayRoot(JsonNode? node) => node is JsonObject;","tryCatchPattern":"try { var root = await store.LoadAsync(ct); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"must contain a JSON object\"))\n{\n    logger.LogWarning(ex, \"Overlay file malformed; starting from empty overlay.\");\n    root = new JsonObject();\n}","preventionTips":["Never hand-edit the overlay into a non-object root; validate JSON after manual edits.","Restrict write access to the overlay file to the application.","Add a startup sanity check that parses the overlay and reports schema problems early."],"tags":["json","file","schema","shell-overlay"],"backgroundTag":"json-parse-error","analyzedSha":"fe9217bdfa0e27f0e09e45006eb6898f616e513d","analyzedAt":"2026-09-13T20:32:34.702Z","contentChangedAt":"2026-09-13T20:32:34.702Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}