{"record":{"id":"c2a7c81e9ad4c5e4","repo":"dotnet/machinelearning","slug":"unknown-option-type","errorCode":null,"errorMessage":"unknown option type","messagePattern":"unknown option type","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.ML.SearchSpace/Converter/OptionConverter.cs","lineNumber":42,"sourceCode":"                // try choice option\n            }\n\n            try\n            {\n                return JsonSerializer.Deserialize<ChoiceOption>(ref reader, options);\n            }\n            catch (Exception)\n            {\n                // try numeric option\n            }\n\n            try\n            {\n                return JsonSerializer.Deserialize<UniformNumericOption>(ref reader, options);\n            }\n            catch (Exception)\n            {\n                throw new ArgumentException(\"unknown option type\");\n            }\n        }\n\n        public override void Write(Utf8JsonWriter writer, OptionBase value, JsonSerializerOptions options)\n        {\n            if (value is SearchSpace ss)\n            {\n                JsonSerializer.Serialize(writer, ss, options);\n            }\n            else if (value is ChoiceOption choiceOption)\n            {\n                JsonSerializer.Serialize(writer, choiceOption, options);\n            }\n            else if (value is UniformNumericOption uniformNumericOption)\n            {\n                JsonSerializer.Serialize(writer, uniformNumericOption, options);\n            }\n            else","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/dotnet/machinelearning/blob/7b76e69cf964daeca3f1377af6bc5543284d56c6/src/Microsoft.ML.SearchSpace/Converter/OptionConverter.cs#L24-L60","documentation":"OptionConverter.Read decides which concrete option type to deserialize by peeking at the JSON (trying SearchSpace and UniformNumericOption shapes). When the JSON matches neither — e.g. it's a categorical/choice option or arbitrary object — the inner deserialization throws and is replaced with ArgumentException 'unknown option type'.","triggerScenarios":"Deserializing JSON into OptionBase where the payload is a non-numeric option (NestOption/ChoiceOption/Schema_ or custom option) or malformed JSON, so neither the SearchSpace nor UniformNumericOption Deserialize branch succeeds.","commonSituations":"Round-tripping search spaces containing categorical (choice) options through a serializer that lost type info; JSON written by an older/newer version with different shape; hand-edited config JSON that doesn't match either expected schema.","solutions":["Inspect the JSON payload: numeric options should have min/max/log_base/default; a search space is an object of named options.","If the payload is a categorical option, deserialize with the appropriate converter or store type information alongside the JSON.","Upgrade/align ML.NET versions on both writer and reader so the JSON shapes match.","Fix malformed JSON so it matches one of the supported option schemas."],"exampleFix":"// before: choice option JSON fed to OptionBase deserialization\n{ \"choices\": [\"a\", \"b\"] }  // -> ArgumentException: unknown option type\n// after: deserialize as its concrete type\nJsonSerializer.Deserialize<ChoiceOption>(json, options);","handlingStrategy":"validation","validationCode":"// C#: peek at JSON to confirm it's a supported option shape before deserializing\nusing var doc = JsonDocument.Parse(json);\nvar root = doc.RootElement;\nbool isSearchSpace = root.ValueKind == JsonValueKind.Object && !root.TryGetProperty(\"choices\", out _);\nbool isNumeric = root.TryGetProperty(\"min\", out _) && root.TryGetProperty(\"max\", out _);\nif (!isSearchSpace && !isNumeric)\n    throw new ArgumentException(\"JSON is neither a search space nor a numeric option\");","typeGuard":"static bool IsNumericOptionJson(JsonElement e) =>\n    e.ValueKind == JsonValueKind.Object && e.TryGetProperty(\"min\", out _) && e.TryGetProperty(\"max\", out _);","tryCatchPattern":"try { opt = JsonSerializer.Deserialize<OptionBase>(json, options); }\ncatch (ArgumentException ex) when (ex.Message == \"unknown option type\")\n{\n    // deserialize with the concrete option type (e.g. ChoiceOption) instead\n}","preventionTips":["Persist a discriminator/type field with serialized options so round-trips are lossless.","Only round-trip options through the same (or newer) ML.NET version.","Unit-test round-trip serialization for all option kinds in your search spaces."],"tags":["json","deserialization","searchspace","type-mismatch"],"backgroundTag":"json-unmarshal-failed","analyzedSha":"7b76e69cf964daeca3f1377af6bc5543284d56c6","analyzedAt":"2026-09-11T12:35:38.930Z","contentChangedAt":"2026-09-11T12:35:38.930Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}