{"record":{"id":"16fd307420a0f79e","repo":"microsoft/aspire","slug":"the-configuration-file-0-must-contain-a-json-object","errorCode":null,"errorMessage":"The configuration file '{0}' must contain a JSON object.","messagePattern":"The configuration file '(.+?)' must contain a JSON object\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Cli/Agents/McpConfigFileHelper.cs","lineNumber":95,"sourceCode":"\n        if (preprocessContent is not null)\n        {\n            content = preprocessContent(content);\n        }\n\n        JsonNode? root;\n        try\n        {\n            root = JsonNode.Parse(content);\n        }\n        catch (JsonException ex)\n        {\n            throw new InvalidOperationException(\n                string.Format(CultureInfo.CurrentCulture, AgentCommandStrings.MalformedConfigFileError, configFilePath), ex);\n        }\n\n        return root as JsonObject\n            ?? throw new InvalidOperationException(\n                string.Format(CultureInfo.CurrentCulture, ErrorStrings.ConfigurationFileMustBeJsonObject, configFilePath));\n    }\n}\n","sourceCodeStart":77,"sourceCodeEnd":99,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Cli/Agents/McpConfigFileHelper.cs#L77-L99","documentation":"After parsing successfully, ReadConfigAsync requires the configuration file's root to be a JSON object. This error is thrown when the file contains valid JSON whose root is an array, string, number, or null instead of an object. The MCP config schema requires an object at the top level (e.g. { \"mcpServers\": { ... } }).","triggerScenarios":"Thrown when `root as JsonObject` is null after JsonNode.Parse succeeds — i.e. the config file's top-level value is an array (e.g. [ ... ]), a bare string/number, or null rather than an object.","commonSituations":"A hand-edit or merge tool replaced the object with an array; a script wrote a bare JSON list of servers instead of an object; the file was truncated to a fragment that happens to parse (e.g. just \"null\").","solutions":["Rewrite the file so its top level is a JSON object, e.g. { \"mcpServers\": { ... } }, moving any array content under an appropriate key.","Compare against a known-good mcp.json schema/template and re-add your entries inside the object.","Delete the malformed file and re-run the CLI command to regenerate a correct skeleton, then re-apply settings.","Validate with `jq 'type' <file>` — it should print \"object\" before you retry."],"exampleFix":"// before\n[ { \"name\": \"fs\" } ]\n// after\n{ \"mcpServers\": { \"fs\": { \"command\": \"npx\" } } }","handlingStrategy":"validation","validationCode":"using var doc = System.Text.Json.JsonDocument.Parse(File.ReadAllText(mcpJsonPath));\nif (doc.RootElement.ValueKind != System.Text.Json.JsonValueKind.Object)\n{\n    // rewrite the file so the top level is an object\n}","typeGuard":null,"tryCatchPattern":"try\n{\n    await command.ExecuteAsync();\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"must contain a JSON object\"))\n{\n    // back up the file, regenerate config, re-add entries\n}","preventionTips":["Keep the top level of mcp.json as an object (e.g. { \"mcpServers\": {...} }).","Check `jq 'type' file` equals \"object\" before running commands against the config.","Avoid merge tools that convert object configs into arrays."],"tags":["json","config","schema","cli"],"backgroundTag":"schema-validation-failed","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}