dotnet/wpf · error · ArgumentException

SR.OptimalParagraphMustWrap

Error message

SR.OptimalParagraphMustWrap

What it means

TextFormatterImp.CreateParagraphCache throws ArgumentException(SR.OptimalParagraphMustWrap) when a TextFormattingSettings/ParagraphProperties specifies OptimalBreak=true but Wrap=false. Optimal paragraph formatting (line breaking algorithm) inherently depends on wrapping to compute optimal break points, so the combination is rejected.

Solutions

  1. Set TextWrapping to Wrap (or WrapWithOverflow) whenever OptimalBreak is true.
  2. Set OptimalBreak = false if the text is intentionally non-wrapping.
  3. Add a guard in property-change handlers so OptimalBreak and Wrap are kept consistent.

Example fix

// before
var paraProps = new TextParagraphProperties {
    TextWrapping = TextWrapping.NoWrap,
    OptimalBreak = true // throws
};
// after
var paraProps = new TextParagraphProperties {
    TextWrapping = TextWrapping.Wrap,
    OptimalBreak = true
};
Defensive patterns

Strategy: validation

Validate before calling

if (paraProps.OptimalBreak && paraProps.TextWrapping == TextWrapping.NoWrap)
    paraProps.TextWrapping = TextWrapping.Wrap; // or set OptimalBreak = false

Type guard

bool OptimalBreakIsValid(bool optimalBreak, TextWrapping wrap) => !optimalBreak || wrap != TextWrapping.NoWrap;

Try / catch

try { formatter.FormatLine(source, start, width, paraProps, null); }
catch (ArgumentException ex) when (ex.Message.Contains("Optimal")) { paraProps.TextWrapping = TextWrapping.Wrap; /* retry */ }

Prevention

When it happens

Trigger: Setting TextParagraphProperties.OptimalBreak to true while TextWrapping is set to NoWrap (TextWrapping.NoWrap on a TextBlock or ParagraphProperties), then creating an optimal-formatting paragraph cache.

Common situations: Enabling optimal paragraph algorithm (for justified CJK/Korean text) on a TextBlock with TextWrapping.NoWrap; copy-pasting style settings that disable wrap; dynamic styling toggling wrap off while OptimalBreak stays on.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/TextFormatting/TextFormatterImp.cs:376

            FormatSettings settings = PrepareFormatSettings(
                textSource,
                firstCharIndex,
                paragraphWidth,
                paragraphProperties,
                previousLineBreak,
                textRunCache,
                true,   // optimalBreak
                false,  // !isSingleLineFormatting
                _textFormattingMode
                );

            //
            // Optimal paragraph formatting session specific check
            //
            if (!settings.Pap.Wrap && settings.Pap.OptimalBreak)
            {
                // Optimal paragraph must wrap.
                throw new ArgumentException(SR.OptimalParagraphMustWrap);
            }

            // create paragraph content cache object
            return new TextParagraphCache(
                settings,
                firstCharIndex,
                RealToIdeal(paragraphWidth)
                );
        }



        /// <summary>
        /// Validate all the relevant text formatting initial settings and package them
        /// </summary>
        private FormatSettings PrepareFormatSettings(
            TextSource                  textSource,
            int                         firstCharIndex,

View on GitHub (pinned to 81131a70a4)