{"record":{"id":"584fcb8dd1e7fb0a","repo":"dotnet/wpf","slug":"propertyofclasscannotbenull-typeface-textrunproperties","errorCode":null,"errorMessage":"PropertyOfClassCannotBeNull (Typeface, TextRunProperties)","messagePattern":"PropertyOfClassCannotBeNull \\(Typeface, TextRunProperties\\)","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/TextFormatting/TextRunCacheImp.cs","lineNumber":131,"sourceCode":"\n                    if (properties == null)\n                        throw new ArgumentException(SR.TextRunPropertiesCannotBeNull);\n\n                    if (properties.FontRenderingEmSize <= 0)\n                        throw new ArgumentException(SR.Format(SR.PropertyOfClassMustBeGreaterThanZero, \"FontRenderingEmSize\", \"TextRunProperties\"));\n\n                    double realMaxFontRenderingEmSize = Constants.RealInfiniteWidth / Constants.GreatestMutiplierOfEm;\n\n                    if (properties.FontRenderingEmSize > realMaxFontRenderingEmSize)\n                        throw new ArgumentException(SR.Format(SR.PropertyOfClassCannotBeGreaterThan, \"FontRenderingEmSize\", \"TextRunProperties\", realMaxFontRenderingEmSize));\n\n                    CultureInfo culture = CultureMapper.GetSpecificCulture(properties.CultureInfo);\n\n                    if (culture == null)\n                        throw new ArgumentException(SR.Format(SR.PropertyOfClassCannotBeNull, \"CultureInfo\", \"TextRunProperties\"));\n\n                    if (properties.Typeface == null)\n                        throw new ArgumentException(SR.Format(SR.PropertyOfClassCannotBeNull, \"Typeface\", \"TextRunProperties\"));\n                }\n\n\n                //\n                // TextRun is specifial to SpanVector because TextRun also encodes position which needs to be \n                // consistent with the positions encoded by SpanVector. In run cache, the begining of a span \n                // should always correspond to the begining of a cached text run. If the end of the currently fetched \n                // run overlaps with the begining of an already cached run, the begining of the cached run needs to be \n                // adjusted as well as its span. Because we can't gurantee the correctness of the overlapped range \n                // so we'll simply remove the overlapped runs here.\n                //                \n\n                // Move the rider to the end of the current run\n                textRunSpanRider.At(cpFetch + textRun.Length - 1);\n                _latestPosition = textRunSpanRider.SpanPosition;\n\n                if (textRunSpanRider.CurrentElement != _textRunVector.Default)\n                {","sourceCodeStart":113,"sourceCodeEnd":149,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/TextFormatting/TextRunCacheImp.cs#L113-L149","documentation":"FetchTextRun finally checks that properties.Typeface is non-null and throws ArgumentException(SR.PropertyOfClassCannotBeNull with Typeface/TextRunProperties). The typeface drives glyph selection and run shaping, so it is mandatory per-run.","triggerScenarios":"A TextRun whose TextRunProperties.Typeface is null is fetched by the run cache during line formatting.","commonSituations":"Custom TextRunProperties not initializing Typeface; fallback font resolution failing silently and leaving null; copy constructors omitting the typeface field.","solutions":["Set Typeface on the run's TextRunProperties (e.g. new Typeface(\"Segoe UI\"))","Resolve fonts via FontFamily/Typeface combination rather than leaving null","Validate each run's properties in your TextSource before returning it"],"exampleFix":"// before\npublic override Typeface Typeface => null;\n// after\npublic override Typeface Typeface => new Typeface(\"Segoe UI\");","handlingStrategy":"type-guard","validationCode":"if (run.Properties?.Typeface == null) run.Properties.Typeface = new Typeface(\"Segoe UI\");","typeGuard":"bool HasTypeface(TextRun r) => r?.Properties?.Typeface != null;","tryCatchPattern":"try { formatter.FormatLine(...); } catch (ArgumentException) { /* set typeface and retry */ }","preventionTips":["Always set Typeface in TextRunProperties implementations","Handle font resolution failures so fallbacks never leave Typeface null"],"tags":["wpf","text-formatting","invalid-argument","typeface"],"backgroundTag":"invalid-argument","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-21T21:30:21.729Z"}