dotnet/wpf · error · NotSupportedException

SR.General_ObjectIsReadOnly

Error message

SR.General_ObjectIsReadOnly

What it means

FamilyTypeface instances can be created read-only (_readOnly true), typically when they represent device font metrics returned from a composite font. VerifyChangeable throws NotSupportedException for any setter — Style, Weight, Stretch, UnderlinePosition, UnderlineThickness, StrikethroughPosition — on a read-only typeface.

Solutions

  1. Construct a new writable FamilyTypeface with new FontFamily(typeface) copy semantics, set the desired properties, and use that instance.
  2. Copy all needed property values into a fresh FamilyTypeface before mutating.
  3. If you own the creation path, keep a mutable instance and only hand out read-only copies to consumers.

Example fix

// before
var tf = fontFamily.FamilyTypefaces[0];
tf.Weight = FontWeights.Bold; // NotSupportedException
// after
var tf = new FontFamily(fontFamily.FamilyTypefaces[0]); // writable copy
tf.Weight = FontWeights.Bold;
Defensive patterns

Strategy: type-guard

Validate before calling

// FamilyTypeface does not expose IsReadOnly; guard by only mutating instances you constructed yourself.

Type guard

static bool IsWritable(FamilyTypeface tf) => tf != null && !IsKnownReadOnlyInstance(tf); // track provenance; only new FamilyTypeface(...) instances are safely writable

Try / catch

try { tf.Weight = FontWeights.Bold; }
catch (NotSupportedException) { tf = new FamilyTypeface(tf) { Weight = FontWeights.Bold }; }

Prevention

When it happens

Trigger: Setting any of Style, Weight, Stretch, UnderlinePosition, UnderlineThickness, or StrikethroughPosition on a FamilyTypeface whose _readOnly flag is set (e.g. a typeface obtained from the family's read-only typeface collection rather than a newly constructed one).

Common situations: Fetching a FamilyTypeface from FontFamily.FamilyTypefaces and trying to tweak its metrics in place, or modifying a typeface after it was contributed to a frozen/read-only composite font.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/89ce5873a8068eb6. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/FamilyTypeface.cs:270

        public override bool Equals(object o)
        {
            return Equals(o as FamilyTypeface);
        }

        /// <summary>
        /// <see cref="object.GetHashCode"/>
        /// </summary>
        public override int GetHashCode()
        {
            return  _style.GetHashCode()
                  ^ _weight.GetHashCode()
                  ^ _stretch.GetHashCode();
        }

        private void VerifyChangeable()
        {
            if (_readOnly)
                throw new NotSupportedException(SR.General_ObjectIsReadOnly);
        }

        string IDeviceFont.Name
        {
            get { return _deviceFontName; }
        }

        bool IDeviceFont.ContainsCharacter(int unicodeScalar)
        {
            return _characterMetrics != null && _characterMetrics.GetValue(unicodeScalar) != null;
        }


        unsafe void IDeviceFont.GetAdvanceWidths(
            char*   characterString,
            int     characterLength,
            double  emSize,
            int*    pAdvances

View on GitHub (pinned to 81131a70a4)