{"record":{"id":"87c969de0bb29e11","repo":"tui-cs/Terminal.Gui","slug":"propertytype-name-converter-convertertype-ful","errorCode":null,"errorMessage":"{propertyType.Name}: Converter \"{converterType.FullName}\" does not expose a compatible Write method.","messagePattern":"(.+?): Converter \"(.+?)\" does not expose a compatible Write method\\.","errorType":"exception","errorClass":"JsonException","httpStatus":null,"severity":"error","filePath":"Terminal.Gui/Configuration/ScopeJsonConverter.cs","lineNumber":385,"sourceCode":"    private static bool TryWriteWithDynamicConverter (Utf8JsonWriter writer, Type propertyType, Type converterType, object value, JsonSerializerOptions options)\n    {\n        if (!RuntimeFeature.IsDynamicCodeSupported)\n        {\n            return false;\n        }\n\n        object converter = Activator.CreateInstance (converterType)!;\n\n        if (converter is JsonConverterFactory factory && factory.CanConvert (propertyType))\n        {\n            converter = factory.CreateConverter (propertyType, options)!;\n        }\n\n        MethodInfo? writeMethod = converter.GetType ().GetMethod (nameof (Write), [typeof (Utf8JsonWriter), propertyType, typeof (JsonSerializerOptions)]);\n\n        if (writeMethod is null)\n        {\n            throw new JsonException ($\"{propertyType.Name}: Converter \\\"{converterType.FullName}\\\" does not expose a compatible Write method.\");\n        }\n\n        try\n        {\n            writeMethod.Invoke (converter, [writer, value, options]);\n\n            return true;\n        }\n        catch (TargetInvocationException e) when (e.InnerException is { })\n        {\n            throw new JsonException ($\"{propertyType.Name}: Error writing property with converter \\\"{converterType.FullName}\\\".\", e.InnerException);\n        }\n    }\n\n    private static bool TryWriteWithKnownConverter (Utf8JsonWriter writer, Type propertyType, Type converterType, object? value, JsonSerializerOptions options)\n    {\n        if (converterType == typeof (ConcurrentDictionaryJsonConverter<ThemeScope>))\n        {","sourceCodeStart":367,"sourceCodeEnd":403,"githubUrl":"https://github.com/tui-cs/Terminal.Gui/blob/2e47b11478db083499917f2ad27c34d30efb0df1/Terminal.Gui/Configuration/ScopeJsonConverter.cs#L367-L403","documentation":"Thrown by TryWriteWithDynamicConverter when a property-level JsonConverter (or the converter produced by a JsonConverterFactory) does not expose a Write method whose signature is exactly Write(Utf8JsonWriter, <propertyType>, JsonSerializerOptions). The converter is found by reflection (GetMethod(nameof(Write), [writer, propertyType, options])) and a null result means no matching overload exists — typically because the converter is typed against a base/different type, or is a JsonConverterFactory that returned a converter for the wrong type.","triggerScenarios":"A config property is decorated with [JsonConverter(typeof(SomeConverter))] where SomeConverter : JsonConverter<BaseType> but the property type is a derived type, so there is no Write(Utf8JsonWriter, DerivedType, ...) method. Also when a JsonConverterFactory.CreateConverter returns a converter that doesn't match propertyType.","commonSituations":"Reusing a generic converter across an inheritance hierarchy; a converter written for an interface applied to a concrete class; version skew where the converter targets an older type.","solutions":["Make the converter generic or write a JsonConverterFactory that returns a converter parameterized by the exact property type.","Align the property's declared type with the type the converter's Write method accepts.","Drop the converter and let the source generator handle serialization for that property."],"exampleFix":"// before\npublic class SchemeConverter : JsonConverter<SchemeBase> { ... }\n[JsonConverter (typeof (SchemeConverter))]\npublic static MyScheme MyProp { get; set; } // MyScheme : SchemeBase -> no Write(MyScheme,...)\n\n// after - use a factory\npublic class SchemeConverterFactory : JsonConverterFactory\n{\n    public override JsonConverter? CreateConverter (Type typeToConvert, JsonSerializerOptions o)\n        => (JsonConverter?)Activator.CreateInstance (typeof (SchemeConverter<>).MakeGenericType (typeToConvert));\n}","handlingStrategy":"type-guard","validationCode":"// Verify a converter exposes a compatible Write before relying on it\nbool HasCompatibleWrite (object converter, Type propertyType)\n    => converter.GetType ().GetMethod (nameof (JsonConverter<object>.Write),\n        [typeof (Utf8JsonWriter), propertyType, typeof (JsonSerializerOptions)]) is not null;","typeGuard":"static bool ConverterSupportsWrite (JsonConverter c, Type propType)\n    => c.GetType ().GetMethod (\"Write\", [typeof (Utf8JsonWriter), propType, typeof (JsonSerializerOptions)]) is not null;","tryCatchPattern":"try { sourcesManager.ToJson (scope); }\ncatch (JsonException ex) when (ex.Message.Contains (\"does not expose a compatible Write method\"))\n{ /* replace converter with a factory or align types */ }","preventionTips":["Type converters' Write against the exact property type, not a base type.","Use JsonConverterFactory when one converter logic spans multiple types.","Add a reflection-based smoke test that checks every config converter exposes Write for its property type."],"tags":["config","json","serialization","converter","reflection"],"backgroundTag":null,"analyzedSha":"2e47b11478db083499917f2ad27c34d30efb0df1","analyzedAt":"2026-08-13T19:20:08.826Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}