dotnet/wpf · error · ArgumentException

throw new…

Error message

throw new ArgumentException(SR.InvalidLinearWhiteSpaceCharacter);

What it means

During ContentType parsing, ValidateCarriageReturns ensures every '\r' is part of a proper '\r\n' (or '\n\r') pair used as LWS folding. An isolated carriage return or stray line-feed inside the content type throws ArgumentException (InvalidLinearWhiteSpaceCharacter).

Solutions

  1. Strip all control characters/newlines from the content type string before construction.
  2. Replace "\r\n" sequences with a single space if folding was intended.
  3. Sanitize at input boundary: filter chars outside the printable token/parameter grammar.

Example fix

// before
var ct = new ContentType("text/plain" + Environment.NewLine);
// after
var ct = new ContentType(("text/plain" + Environment.NewLine).Trim(new[] {'\r','\n',' ','\t'}));
Defensive patterns

Strategy: validation

Validate before calling

public static string StripControlChars(string s) =>
    new string(s.Where(c => !char.IsControl(c)).ToArray());

Try / catch

try { var ct = new ContentType(value); }
catch (ArgumentException ex) when (ex.Message.Contains("white space character"))
{ value = StripControlChars(value); }

Prevention

When it happens

Trigger: new ContentType(...) with a string containing a bare '\r' not adjacent to '\n' (or bare '\n' not adjacent to '\r'), e.g. values assembled by string concatenation with Environment.NewLine on mixed conventions or raw multi-line input.

Common situations: Content types copied from headers with line folding, files with Windows/Unix newline mismatch, template-built strings where a newline slipped in.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/ContentType.cs:395

        /// <param name="contentType"></param>
        private static void ValidateCarriageReturns(string contentType)
        {
            Debug.Assert(!IsLinearWhiteSpaceChar(contentType[0]) && !IsLinearWhiteSpaceChar(contentType[contentType.Length - 1]));

            //Prior to calling this method we have already checked that first and last
            //character of the content type are not Linear White Spaces. So its safe to
            //assume that the index will be greater than 0 and less that length-2.

            int index = contentType.IndexOf(_linearWhiteSpaceChars[2]);
            
            while (index != -1)
            {
                if (contentType[index - 1] == _linearWhiteSpaceChars[1] || contentType[index + 1] == _linearWhiteSpaceChars[1])
                {
                    index = contentType.IndexOf(_linearWhiteSpaceChars[2], ++index);
                }
                else
                    throw new ArgumentException(SR.InvalidLinearWhiteSpaceCharacter);
            }
        }

        /// <summary>
        /// Parses the type ans subType tokens from the string. 
        /// Also verifies if the Tokens are valid as per the grammar.
        /// </summary>
        /// <param name="typeAndSubType">substring that has the type and subType of the content type</param>
        /// <exception cref="ArgumentException">If the typeAndSubType parameter does not have the "/" character</exception>
        private void ParseTypeAndSubType(ReadOnlySpan<char> typeAndSubType)
        {
            //okay to trim at this point the end of the string as Linear White Spaces(LWS) chars are allowed here.
            typeAndSubType = typeAndSubType.TrimEnd(_linearWhiteSpaceChars);

            int forwardSlashPos = typeAndSubType.IndexOf('/');
            if (forwardSlashPos < 0 || // no slashes
                typeAndSubType.Slice(forwardSlashPos + 1).IndexOf('/') >= 0) // more than one slash
            {

View on GitHub (pinned to 81131a70a4)