jstedfast/MailKit · error · InvalidOperationException

The HeaderSet is read-only.

Error message

The HeaderSet is read-only.

What it means

HeaderSet implements a read-only mode (IsReadOnly). Any mutating method (Exclude, Add, AddRange, Clear, Remove) calls CheckReadOnly, which throws InvalidOperationException when the set is frozen. MailKit marks header sets read-only when they are shared/frozen state that must not change (e.g. a fixed query header list).

Solutions

  1. Clone or create a new mutable HeaderSet instead of mutating the read-only one
  2. Check IsReadOnly before mutating and unfreeze/replace if a mutable setter exists
  3. Construct a fresh HeaderSet and add the desired headers

Example fix

// before
readOnlySet.Add (HeaderId.Subject); // throws
// after
var set = new HeaderSet (HeaderId.Subject);
Defensive patterns

Strategy: type-guard

Validate before calling

if (set.IsReadOnly)
    set = new HeaderSet (set.ToArray ()); // work on a mutable copy

Type guard

static bool CanMutate (HeaderSet s) => s != null && !s.IsReadOnly;

Try / catch

try {
    set.Add (HeaderId.Subject);
} catch (InvalidOperationException) {
    set = new HeaderSet (HeaderId.Subject); // recreate mutable set
}

Prevention

When it happens

Trigger: Calling Add/AddRange/Remove/Clear/Exclude on a HeaderSet whose IsReadOnly is true.

Common situations: Reusing a HeaderSet instance obtained from or attached to an immutable query/frozen state; accidentally freezing a set and later trying to mutate it; sharing one HeaderSet across threads or queries.

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 jstedfast/MailKit@9d3859a785 (2026-09-15). Data as JSON: /api/errors/8b33da1368f9a9a5. Report an issue: GitHub.

Appendix: source

Thrown at MailKit/HeaderSet.cs:125

			AddRange (headers);
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="HeaderSet"/> class.
		/// </summary>
		/// <remarks>
		/// Creates a new <see cref="HeaderSet"/>.
		/// </remarks>
		/// <param name="headers">The headers to include.</param>
		public HeaderSet (IEnumerable<string> headers)
		{
			AddRange (headers);
		}

		void CheckReadOnly ()
		{
			if (IsReadOnly)
				throw new InvalidOperationException ("The HeaderSet is read-only.");
		}

		/// <summary>
		/// Get the number of headers in the set.
		/// </summary>
		/// <remarks>
		/// Gets the number of headers in the set.
		/// </remarks>
		/// <value>The number of headers.</value>
		public int Count {
			get { return hash.Count; }
		}

		/// <summary>
		/// Get or set whether this set of headers is meant to be excluded when used with a <see cref="IFetchRequest"/>.
		/// </summary>
		/// <remarks>
		/// Get or set whether this set of headers is meant to be excluded when used with a <see cref="IFetchRequest"/>.

View on GitHub (pinned to 9d3859a785)