{"record":{"id":"f3b0db9b073f3d83","repo":"microsoft/aspire","slug":"claimedsectionsproperty-must-be-a-json-string","errorCode":null,"errorMessage":"'{ClaimedSectionsProperty}' must be a JSON string.","messagePattern":"'(.+?)' must be a JSON string\\.","errorType":"exception","errorClass":"InvalidDataException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting/Pipelines/Internal/FileDeploymentStateManager.cs","lineNumber":759,"sourceCode":"        return File.Exists(migrationStatePath)\n            ? ParseMigrationState(LoadStateFile(migrationStatePath))\n            : new(false, [], [], null);\n    }\n\n    private static MigrationState ParseMigrationState(JsonObject migrationState)\n    {\n        var legacyFallbackDisabled = migrationState[LegacyFallbackDisabledProperty]?.GetValue<bool>() ?? false;\n        var legacyStateSnapshot = migrationState[LegacyStateProperty] switch\n        {\n            null => [],\n            JsonObject legacyState => legacyState,\n            _ => throw new InvalidDataException($\"'{LegacyStateProperty}' must be a JSON object.\")\n        };\n        var claimedSectionNames = migrationState[ClaimedSectionsProperty] switch\n        {\n            null => [],\n            JsonValue claimedSectionsValue => ParseClaimedSectionNames(claimedSectionsValue),\n            _ => throw new InvalidDataException($\"'{ClaimedSectionsProperty}' must be a JSON string.\")\n        };\n        var currentState = migrationState[CurrentStateProperty] switch\n        {\n            null => null,\n            JsonValue stateValue => JsonNode.Parse(stateValue.GetValue<string>())?.AsObject()\n                ?? throw new InvalidDataException($\"'{CurrentStateProperty}' must contain a JSON object.\"),\n            _ => throw new InvalidDataException($\"'{CurrentStateProperty}' must be a JSON string.\")\n        };\n\n        return new(legacyFallbackDisabled, legacyStateSnapshot, claimedSectionNames, currentState);\n    }\n\n    private static string[] ParseClaimedSectionNames(JsonValue claimedSectionsValue)\n    {\n        var claimedSectionNames = JsonSerializer.Deserialize<string?[]>(\n            claimedSectionsValue.GetValue<string>());\n        if (claimedSectionNames is null ||\n            claimedSectionNames.Any(string.IsNullOrWhiteSpace))","sourceCodeStart":741,"sourceCodeEnd":777,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting/Pipelines/Internal/FileDeploymentStateManager.cs#L741-L777","documentation":"The migration state record requires the 'claimedSections' property to be either absent/null or a JSON value parseable as an array of section-name strings; any other JSON type throws InvalidDataException. It tracks which sections have been claimed during the state-file migration.","triggerScenarios":"Loading a migration/state file where claimedSections is an object, number, boolean, or array of non-strings instead of a JSON string/value parseable to string names.","commonSituations":"Hand edits to the state file; corruption from a crashed write; mixing state files produced by different Aspire versions with different schemas.","solutions":["Set claimedSections to the expected string form (e.g. a JSON string or array of strings naming claimed sections) or remove the property.","Delete the corrupt migration state file and re-run the deployment to regenerate it.","Avoid manual edits; let the pipeline own this file."],"exampleFix":"// before (state file)\n{ \"claimedSections\": { \"sectionA\": true } }\n// after\n{ \"claimedSections\": [\"sectionA\"] }","handlingStrategy":"validation","validationCode":"// Validate before handing the file to the manager\nif (migrationState[\"claimedSections\"] is not (null or JsonValue))\n{\n    throw new InvalidDataException(\"claimedSections must be a JSON string (or absent).\");\n}","typeGuard":"static bool HasValidClaimedSections(JsonObject migrationState) =>\n    migrationState[\"claimedSections\"] is null or JsonValue;","tryCatchPattern":"try { await manager.LoadStateAsync(ct); }\ncatch (InvalidDataException ex) when (ex.Message.Contains(\"claimedSections\") && ex.Message.Contains(\"JSON string\"))\n{\n    File.Move(statePath, statePath + \".corrupt\", overwrite: true);\n    // proceed as if no sections were claimed\n}","preventionTips":["Treat the migration state file as tool-owned; avoid manual edits.","Round-trip edits through System.Text.Json to preserve property types.","Keep state files from being rewritten by external scripts."],"tags":["json","state-file","migration","type-mismatch"],"backgroundTag":"type-mismatch","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"}