dotnet/wpf · error · InvalidOperationException

Returned string is too long for the buffer provided.

Error message

Returned string is too long for the buffer provided.

What it means

WPF's IndexingFilterMarshaler implements the COM IFilter interface so Windows Search can index XPS/package content. When a host calls IFilter::GetText, MarshalStringToPtr copies the filter's text into a caller-provided character buffer sized by bufCharacterCount. The contract requires room for the string plus a terminating null, so when s.Length > bufCharacterCount - 1 the marshaler throws InvalidOperationException because it can neither truncate the text nor overrun the buffer.

Solutions

  1. Allocate a buffer of at least (chunk text length + 1) characters before calling GetText and pass that count in bufCharacterCount
  2. Catch the exception, grow the buffer, and retry the GetText call
  3. If you control the filter's text source, split long strings so each fits the advertised buffer size
  4. Verify the host counts characters (WCHARs), not bytes — a byte/char confusion makes buffers appear half-size

Example fix

// before: fixed 64-char buffer regardless of text
char[] buf = new char[64];
uint count = 64;
filter.GetText(ref count, buf);

// after: size the buffer for the chunk text plus terminating null
string text = chunk.Text;
char[] buf = new char[text.Length + 1];
uint count = (uint)buf.Length;
filter.GetText(ref count, buf);
Defensive patterns

Strategy: try-catch

Validate before calling

if (text != null && bufCharacterCount < (uint)text.Length + 1)
{
    // grow the buffer before calling GetText
    bufCharacterCount = (uint)text.Length + 1;
    buffer = new char[text.Length + 1];
}

Try / catch

try
{
    filter.GetText(ref bufCharacterCount, buffer);
}
catch (InvalidOperationException ex)
{
    // string did not fit: enlarge buffer to text length + 1 and retry
    GrowBufferAndRetry();
}

Prevention

When it happens

Trigger: A search/indexing host calls GetText with a buffer whose bufCharacterCount is less than or equal to the length of the current text chunk string; the check (uint)s.Length > bufCharacterCount - 1 in MarshalStringToPtr fires.

Common situations: Custom IFilter hosts or third-party indexing clients that allocate undersized text buffers when enumerating an XPS document via WPF's filter; hosts that pass bufCharacterCount in bytes instead of characters, halving the effective capacity; buffer-size renegotiation bugs after partial GetText calls.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/IO/Packaging/indexingfiltermarshaler.cs:98

                return null;
        }

        /// <summary>
        /// StringToPtr
        /// </summary>
        /// <remarks>Converts a managed string into the format useful for IFilter.GetText</remarks>
        /// <param name="s">string to convert</param>
        /// <param name="bufCharacterCount">maximum number of characters to convert</param>
        /// <param name="p">pointer to write to</param>
        internal static void MarshalStringToPtr(string s, ref uint bufCharacterCount, IntPtr p)
        {
            // bufCharacterCount is never supposed to be zero at this level.
            Invariant.Assert(bufCharacterCount != 0);

            // ensure the interface rules are followed
            // string must also be null terminated so we restrict the length to buf size - 1
            if ((uint)(s.Length) > bufCharacterCount - 1)
                throw new InvalidOperationException(SR.FilterGetTextBufferOverflow);

            // Return the number of characters written, including the terminating null.
            bufCharacterCount = (UInt32)s.Length + 1;

            // convert string to unmanaged string and write into provided buffer
            Marshal.Copy(s.ToCharArray(), 0, p, s.Length);

            // null terminate (16bit's of zero to replace one Unicode character)
            Marshal.WriteInt16(p, s.Length * _int16Size, 0);
        }

        /// <summary>
        /// Marshal Managed to Native PROPSPEC
        /// </summary>
        /// <param name="propSpec"></param>
        /// <param name="native"></param>
        internal static void MarshalPropSpec(ManagedPropSpec propSpec, ref PROPSPEC native)
        {

View on GitHub (pinned to 81131a70a4)