{"record":{"id":"65a020288c4b1989","repo":"microsoft/semantic-kernel","slug":"failed-to-deserialize-execution-state-for-sessioni","errorCode":null,"errorMessage":"Failed to deserialize execution state for sessionId={sessionId}, data={text}","messagePattern":"Failed to deserialize execution state for sessionId=(.+?), data=(.+?)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"dotnet/src/Experimental/Orchestration.Flow/Execution/FlowStatusProvider.cs","lineNumber":58,"sourceCode":"        this._memoryStore = memoryStore;\n        this._collectionName = collectionName ?? nameof(FlowStatusProvider);\n    }\n\n    /// <inheritdoc/>\n    public async Task<ExecutionState> GetExecutionStateAsync(string sessionId)\n    {\n        var result = await (this._memoryStore.GetAsync(this._collectionName, this.GetExecutionStateStorageKey(sessionId))).ConfigureAwait(false);\n        var text = result?.Metadata.Text ?? string.Empty;\n\n        if (!string.IsNullOrEmpty(text))\n        {\n            try\n            {\n                return JsonSerializer.Deserialize<ExecutionState>(text) ?? new ExecutionState();\n            }\n            catch\n            {\n                throw new InvalidOperationException(\n                    $\"Failed to deserialize execution state for sessionId={sessionId}, data={text}\");\n            }\n        }\n        else\n        {\n            return new ExecutionState();\n        }\n    }\n\n    /// <inheritdoc/>\n    public async Task SaveExecutionStateAsync(string sessionId, ExecutionState state)\n    {\n        var json = JsonSerializer.Serialize(state);\n        await this._memoryStore.UpsertAsync(this._collectionName, this.CreateMemoryRecord(this.GetExecutionStateStorageKey(sessionId), json))\n            .ConfigureAwait(false);\n    }\n\n    private string GetExecutionStateStorageKey(string sessionId)","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/dotnet/src/Experimental/Orchestration.Flow/Execution/FlowStatusProvider.cs#L40-L76","documentation":"FlowStatusProvider loads a serialized ExecutionState from the memory store for a given sessionId. If the stored text fails JSON deserialization into ExecutionState (JsonSerializer.Deserialize throws), the exception is caught and rethrown as InvalidOperationException with the sessionId and raw data text. This guards against resuming a flow from corrupted or incompatible state.","triggerScenarios":"The memory store contains a text record for the session's execution-state key that is not valid JSON for the ExecutionState type. Occurs when state was written by an older/incompatible version, manually edited, or corrupted in storage.","commonSituations":"Deploying a new version of the Orchestration.Flow package where ExecutionState's structure changed, making old serialized states undesharializable. Using a volatile or shared memory store where another process wrote incompatible data. Manual editing or truncation of stored state text.","solutions":["Clear the stored execution state for the affected sessionId and restart the flow from the beginning.","If the ExecutionState schema changed, implement a migration or version field so old states can be upgraded.","Inspect the raw 'data' in the exception message to identify whether it's truncated, malformed, or structurally incompatible.","Ensure only one version of the Orchestration.Flow package writes to the same memory store collection.","Add a schema version property to ExecutionState and validate it before deserialization."],"exampleFix":"// before — old session state from previous version causes crash\nvar state = await statusProvider.GetExecutionStateAsync(sessionId);\n\n// after — catch incompatible state and restart\ntry {\n    var state = await statusProvider.GetExecutionStateAsync(sessionId);\n} catch (InvalidOperationException) {\n    // stale/corrupt state — clear and start fresh\n    await statusProvider.ClearAsync(sessionId);\n    var state = await statusProvider.GetExecutionStateAsync(sessionId);\n}","handlingStrategy":"try-catch","validationCode":"// Pre-call: optionally probe state validity before loading\n// (The provider itself does the deserialize; you can wrap GetExecutionStateAsync)\n// Best prevention: include a schema version in your state and validate it.\nif (!await statusProvider.HasStateAsync(sessionId))\n{\n    // No state — safe to start fresh; no deserialization risk\n}","typeGuard":null,"tryCatchPattern":"ExecutionState state;\ntry\n{\n    state = await statusProvider.GetExecutionStateAsync(sessionId);\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"Failed to deserialize\"))\n{\n    logger.LogWarning(ex, \"Corrupt state for session {Id}; clearing and starting fresh.\", sessionId);\n    await statusProvider.ClearExecutionStateAsync(sessionId);\n    state = new ExecutionState(); // restart clean\n}","preventionTips":["Add a Version property to ExecutionState and reject/ migrate incompatible versions before deserializing.","Clear old session states when deploying a new version of the Orchestration.Flow package.","Don't share a memory-store collection across different versions of the package.","Wrap state loading in try-catch with a fresh-start fallback for production resilience."],"tags":["flow-status","deserialization","state","experimental","orchestration","versioning"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}