{"record":{"id":"57b4c421a87ec86f","repo":"microsoft/aspire","slug":"currentstateproperty-must-be-a-json-string","errorCode":null,"errorMessage":"'{CurrentStateProperty}' 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":766,"sourceCode":"        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))\n        {\n            throw new InvalidDataException(\n                $\"'{ClaimedSectionsProperty}' must contain a JSON array of non-empty strings.\");\n        }\n\n        return [.. claimedSectionNames.Select(static sectionName => sectionName!)];\n    }","sourceCodeStart":748,"sourceCodeEnd":784,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting/Pipelines/Internal/FileDeploymentStateManager.cs#L748-L784","documentation":"The 'currentState' property of the migration state must be a JSON string (the state is embedded serialized). If the property holds a non-string JSON type such as an object, array, or number directly, InvalidDataException is thrown.","triggerScenarios":"Loading a migration state file where currentState was written as a raw JSON object instead of a JSON-escaped string — e.g. by a tool or hand edit that unescaped it.","commonSituations":"Hand-formatting the state file in an editor that unescaped the embedded JSON; an external script rewriting the file without preserving string encoding; schema drift between versions.","solutions":["Re-encode currentState as a JSON string (escape the embedded object) or remove the property.","Delete the file and let the next deployment regenerate it with the correct encoding.","If you scripted state-file edits, serialize the current state with JsonNode/JsonSerializer to a string before writing."],"exampleFix":"// before (state file)\n{ \"currentState\": { \"resources\": {} } }\n// after\n{ \"currentState\": \"{\\\"resources\\\":{}}\" }","handlingStrategy":"validation","validationCode":"// currentState must be a JSON string, not a raw object/array\nif (migrationState[\"currentState\"] is not (null or JsonValue v) ||\n    (v is not null && !v.TryGetValue<string>(out _)))\n{\n    throw new InvalidDataException(\"currentState must be a JSON string.\");\n}","typeGuard":"static bool HasValidCurrentStateType(JsonObject migrationState) =>\n    migrationState[\"currentState\"] is null or JsonValue v && v.TryGetValue<string>(out _);","tryCatchPattern":"try { await manager.LoadStateAsync(ct); }\ncatch (InvalidDataException ex) when (ex.Message.Contains(\"currentState\") && ex.Message.Contains(\"JSON string\"))\n{\n    File.Move(statePath, statePath + \".corrupt\", overwrite: true);\n}","preventionTips":["When editing the file, keep currentState string-escaped; pretty-printers or editors may unescape it.","Use JsonNode.ToJsonString() when writing embedded state.","Don't let external scripts rewrite the state file with raw nested objects."],"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"}