{"record":{"id":"6bc61bf407790876","repo":"microsoft/autogen","slug":"failed-to-clone-options-6bc61b","errorCode":null,"errorMessage":"Failed to clone options","messagePattern":"Failed to clone options","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"dotnet/src/AutoGen.OpenAI.V1/Agent/OpenAIChatAgent.cs","lineNumber":140,"sourceCode":"    }\n\n    private ChatCompletionsOptions CreateChatCompletionsOptions(GenerateReplyOptions? options, IEnumerable<IMessage> messages)\n    {\n        var oaiMessages = messages.Select(m => m switch\n        {\n            IMessage<ChatRequestMessage> chatRequestMessage => chatRequestMessage.Content,\n            _ => throw new ArgumentException(\"Invalid message type\")\n        });\n\n        // add system message if there's no system message in messages\n        if (!oaiMessages.Any(m => m is ChatRequestSystemMessage))\n        {\n            oaiMessages = new[] { new ChatRequestSystemMessage(systemMessage) }.Concat(oaiMessages);\n        }\n\n        // clone the options by serializing and deserializing\n        var json = JsonSerializer.Serialize(this.options);\n        var settings = JsonSerializer.Deserialize<ChatCompletionsOptions>(json) ?? throw new InvalidOperationException(\"Failed to clone options\");\n\n        foreach (var m in oaiMessages)\n        {\n            settings.Messages.Add(m);\n        }\n\n        settings.Temperature = options?.Temperature ?? settings.Temperature;\n        settings.MaxTokens = options?.MaxToken ?? settings.MaxTokens;\n\n        foreach (var functions in this.options.Tools)\n        {\n            settings.Tools.Add(functions);\n        }\n\n        foreach (var stopSequence in this.options.StopSequences)\n        {\n            settings.StopSequences.Add(stopSequence);\n        }","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/microsoft/autogen/blob/027ecf0a379bcc1d09956d46d12d44a3ad9cee14/dotnet/src/AutoGen.OpenAI.V1/Agent/OpenAIChatAgent.cs#L122-L158","documentation":"OpenAIChatAgent clones its stored ChatCompletionsOptions on every call by round-tripping through System.Text.Json. If JsonSerializer.Deserialize returns null (options became null mid-flight or serialization produced 'null'), it throws InvalidOperationException to avoid mutating the shared original.","triggerScenarios":"The agent's options instance was set to null after construction, or a custom JsonSerializerContext/converters caused Serialize(options) to emit \"null\"; the clone step then fails on every request.","commonSituations":"Rare in practice; seen when the options field is mutated by user code via reflection or partial classes, or with SDK version mismatches where ChatCompletionsOptions lost a parameterless serialization shape.","solutions":["Do not mutate or null out the agent's options after construction; treat the agent as immutable","Pin matching versions of the OpenAI .NET SDK and AutoGen.OpenAI.V1","If you need per-call settings, pass them via GenerateReplyOptions instead of rewriting this.options"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"catch (InvalidOperationException ex) when (ex.Message == \"Failed to clone options\")\n{\n    logger.LogCritical(ex, \"Agent options corrupted; recreating agent\");\n    agent = BuildAgent(); // reconstruct with fresh options\n}","preventionTips":["Treat constructed agents as immutable","Keep AutoGen.OpenAI.V1 and the OpenAI SDK versions in sync","Use GenerateReplyOptions for per-call settings"],"tags":["openai","serialization","options-clone","defensive-check"],"backgroundTag":null,"analyzedSha":"027ecf0a379bcc1d09956d46d12d44a3ad9cee14","analyzedAt":"2026-08-15T03:38:00.719Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}