dotnet/wpf · error · InvalidOperationException

Value is read-only.

Error message

Value is read-only.

What it means

The Win32 edit box proxy throws InvalidOperationException(ValueReadonly) from IValueProvider.SetValue when the edit control has the ES_READONLY window style. UIA forbids writing to a control that the underlying Win32 control itself marks read-only.

Solutions

  1. Enable the control first via EM_SETREADOFFSET/no — send EM_SETREADONLY (wParam=0) to the HWND if you own the application.
  2. Use the IValueProvider.IsReadOnly property to check before calling SetValue and skip or warn.
  3. If the field must accept input, fix the application so the control is not read-only.
  4. Automate the underlying data source (e.g. API or config) instead of typing into the read-only UI.

Example fix

// before
var valuePattern = editBox.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
valuePattern.SetValue("text"); // InvalidOperationException: Value is read-only.
// after
var vp = (ValuePattern)editBox.GetCurrentPattern(ValuePattern.Pattern);
if (!vp.Current.IsReadOnly)
{
    vp.SetValue("text");
}
Defensive patterns

Strategy: validation

Validate before calling

var vp = (ValuePattern)el.GetCurrentPattern(ValuePattern.Pattern);
if (vp.Current.IsReadOnly) return; // skip SetValue

Try / catch

try { vp.SetValue(text); }
catch (InvalidOperationException) { /* control is read-only; log and skip */ }

Prevention

When it happens

Trigger: Calling IValueProvider.SetValue on a WindowsEditBox whose window styles include ES_READONLY (set via EM_SETREADONLY or created with the style).

Common situations: Automating a disabled/read-only text field such as a computed field, license key display, or a form field the app locked after data entry; an application dynamically set EM_SETREADONLY before the script attempted input.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/UIAutomation/UIAutomationClientSideProviders/MS/Internal/AutomationProxies/WindowsEditBox.cs:271

        {
            return base.EventToWinEvent(idEvent);
        }

        #endregion

        #region Value Pattern

        // Sets the text of the edit.
        void IValueProvider.SetValue (string str)
        {
            // Ensure that the edit box and all its parents are enabled.
            Misc.CheckEnabled(_hwnd);

            int styles = WindowStyle;

            if (Misc.IsBitSet(styles, NativeMethods.ES_READONLY))
            {
                throw new InvalidOperationException(SR.ValueReadonly);
            }

            // check if control only accepts numbers
            if (Misc.IsBitSet(styles, NativeMethods.ES_NUMBER))
            {
                // check if string contains any non-numeric characters.
                foreach (char ch in str)
                {
                    if (char.IsLetter (ch))
                    {
                        throw new ArgumentException(SR.Format(SR.NotAValidValue, str), "val");
                    }
                }
            }

            // Text/edit box should not enter more characters than what is allowed through keyboard.
            // Determine the max number of chars this editbox accepts
            int result = Misc.ProxySendMessageInt(_hwnd, NativeMethods.EM_GETLIMITTEXT, IntPtr.Zero, IntPtr.Zero);

View on GitHub (pinned to 81131a70a4)