jstedfast/MailKit · error · ImapProtocolException

Literal token length

Error message

Literal token length ({literalLength} bytes) exceeds the maximum allowed size ({MaxLiteralTokenLength} bytes).

What it means

While reading a literal token (ImapStreamMode.Literal) in the synchronous token loop, ImapEngine compares the declared literal length against MaxLiteralTokenLength and throws ImapProtocolException if exceeded. It guards against absurdly large literals from a malicious/broken server, preventing huge memory allocations via ArrayPool rent.

Solutions

  1. Increase ImapEngine's MaxLiteralTokenLength (client client.MaxLiteralTokenLength / engine property) to accommodate your workload.
  2. Avoid fetching the large parts: use BodyStructure/peek and fetch specific body parts instead of whole-message literals.
  3. If the literal size is bogus, treat it as a server bug — validate/capture the server response and report it.
  4. Raise a fresh connection with a larger cap for the specific large fetch.

Example fix

// before
client.Connect(host, 993, true);
var msg = folder.GetMessage(uid); // large literal aborts

// after
client.Connect(host, 993, true);
client.MaxLiteralTokenLength = 50 * 1024 * 1024; // allow larger literals
var msg = folder.GetMessage(uid);
Defensive patterns

Strategy: try-catch

Validate before calling

// before large fetches, compare expected size against the cap
if (expectedSize > client.MaxLiteralTokenLength) client.MaxLiteralTokenLength = (int)(expectedSize * 1.5);

Try / catch

try { msg = folder.GetMessage(uid); } catch (ImapProtocolException ex) when (ex.Message.Contains("Literal token length")) { /* raise cap or fetch body parts instead */ }

Prevention

When it happens

Trigger: Server sends a literal ({NNNN}) whose byte count exceeds MaxLiteralTokenLength during response parsing — e.g. fetching a message/filename literal larger than the configured cap.

Common situations: Fetching very large attachments or header literals from a server while the client's literal cap is low (MaxLiteralTokenLength default tied to max line/literal settings); hostile or misbehaving server sending bogus large literal sizes.

Understand the failure class

Background: payload too large / request exceeds maximum size: why libraries cap bytes and how to fix oversize payloads — this error's family across 50 libraries.

Related errors


AI-assisted analysis of jstedfast/MailKit@9d3859a785 (2026-09-15). Data as JSON: /api/errors/5f1ec056cadbb576. Report an issue: GitHub.

Appendix: source

Thrown at MailKit/Net/Imap/ImapEngine.cs:1215

		/// <param name="cancellationToken">The cancellation token.</param>
		/// <exception cref="System.InvalidOperationException">
		/// The <see cref="Stream"/> is not in literal mode.
		/// </exception>
		/// <exception cref="System.OperationCanceledException">
		/// The operation was canceled via the cancellation token.
		/// </exception>
		/// <exception cref="System.IO.IOException">
		/// An I/O error occurred.
		/// </exception>
		public string ReadLiteral (CancellationToken cancellationToken)
		{
			if (Stream!.Mode != ImapStreamMode.Literal)
				throw new InvalidOperationException ();

			int literalLength = Stream.LiteralLength;

			if (literalLength > MaxLiteralTokenLength)
				throw new ImapProtocolException ($"Literal token length ({literalLength} bytes) exceeds the maximum allowed size ({MaxLiteralTokenLength} bytes).");

			var buf = ArrayPool<byte>.Shared.Rent (literalLength);

			try {
				int n, nread = 0;

				do {
					if ((n = Stream.Read (buf, nread, literalLength - nread, cancellationToken)) == 0)
						break;

					nread += n;
				} while (nread < literalLength);

				return TextEncodings.GetString (buf, 0, nread);
			} finally {
				ArrayPool<byte>.Shared.Return (buf);
			}
		}

View on GitHub (pinned to 9d3859a785)