jstedfast/MailKit · error · NotSupportedException

null

Error message

null

What it means

SmtpStream.Position setter unconditionally throws NotSupportedException: the SMTP protocol stream is sequential and cannot be seeked. The getter delegates to the underlying stream, but setting Position (or calling Seek) makes no sense for a protocol stream that reads server responses in order.

Solutions

  1. Do not set Position on SmtpStream; treat it as a forward-only stream
  2. Check stream.CanSeek before seeking and handle non-seekable streams
  3. Buffer data yourself if you need re-reads

Example fix

// before
smtpStream.Position = 0;
// after
if (smtpStream.CanSeek)
    smtpStream.Position = 0;
else
    throw new InvalidOperationException("SmtpStream is not seekable");
Defensive patterns

Strategy: type-guard

Validate before calling

if (stream.CanSeek) { /* safe */ }

Type guard

bool IsSeekable(Stream s) => s.CanSeek;

Try / catch

try { stream.Position = 0; }
catch (NotSupportedException) { /* copy to seekable stream */ }

Prevention

When it happens

Trigger: Assigning to stream.Position on a SmtpStream obtained from SmtpClient, e.g. generic stream-copy or retry logic that assumes a seekable Stream.

Common situations: Passing the client's internal stream to utilities that rewind streams; code shared between FileStream and network streams assuming CanSeek.

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/54dbdfe772b41d27. Report an issue: GitHub.

Appendix: source

Thrown at MailKit/Net/Smtp/SmtpStream.cs:193

		/// Get or set the position within the current stream.
		/// </summary>
		/// <remarks>
		/// Gets or sets the position within the current stream.
		/// </remarks>
		/// <returns>The current position within the stream.</returns>
		/// <value>The position of the stream.</value>
		/// <exception cref="System.IO.IOException">
		/// An I/O error occurred.
		/// </exception>
		/// <exception cref="System.NotSupportedException">
		/// The stream does not support seeking.
		/// </exception>
		/// <exception cref="System.ObjectDisposedException">
		/// The stream has been disposed.
		/// </exception>
		public override long Position {
			get { return Stream.Position; }
			set { throw new NotSupportedException (); }
		}

		/// <summary>
		/// Get the length of the stream, in bytes.
		/// </summary>
		/// <remarks>
		/// Gets the length of the stream, in bytes.
		/// </remarks>
		/// <returns>A long value representing the length of the stream in bytes.</returns>
		/// <value>The length of the stream.</value>
		/// <exception cref="System.NotSupportedException">
		/// The stream does not support seeking.
		/// </exception>
		/// <exception cref="System.ObjectDisposedException">
		/// The stream has been disposed.
		/// </exception>
		public override long Length {
			get { return Stream.Length; }

View on GitHub (pinned to 9d3859a785)