jstedfast/MailKit · error · ArgumentOutOfRangeException

Can only transform 8 bytes at a time.

Error message

Can only transform 8 bytes at a time.

What it means

DES is a strict 64-bit block cipher, so MailKit's TransformBlock only accepts exactly 8 bytes per call and throws ArgumentOutOfRangeException with message "Can only transform 8 bytes at a time." when inputCount != 8. This follows .NET's block-cipher contract where a block transform processes one block per invocation.

Solutions

  1. Loop over the input in 8-byte chunks, calling TransformBlock once per chunk.
  2. Pad input to a multiple of 8 bytes (NTLM usage pads per its spec) or route the final partial block through TransformFinalBlock as appropriate.
  3. If transforming multiple blocks, call TransformBlock repeatedly rather than passing a larger count.

Example fix

// before
des.TransformBlock(data, 0, data.Length, output, 0); // data.Length may be > 8

// after
for (int i = 0; i + 8 <= data.Length; i += 8)
    des.TransformBlock(data, i, 8, output, i);
Defensive patterns

Strategy: validation

Validate before calling

if (data.Length % 8 != 0) throw new InvalidOperationException("DES input must be padded to a multiple of 8 bytes");
for (int i = 0; i < data.Length; i += 8)
    des.TransformBlock(data, i, 8, output, i);

Type guard

static bool IsBlockAligned(byte[] b) => b != null && b.Length % 8 == 0;

Try / catch

try {
    des.TransformBlock(data, 0, 8, output, 0);
} catch (ArgumentOutOfRangeException ex) when (ex.Message.Contains("8 bytes")) {
    // wrong chunk size: fix the loop stride to 8
}

Prevention

When it happens

Trigger: Calling TransformBlock with any inputCount other than 8 (e.g., 16 to 'transform two blocks', or a leftover 3-byte tail of a stream).

Common situations: Trying to process a whole buffer in one call instead of looping in 8-byte chunks; passing a non-padded plaintext length; porting code from a streaming cipher that accepted arbitrary lengths.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at MailKit/Security/Ntlm/DES.cs:117

			}

			public int OutputBlockSize {
				get { return 8; }
			}

			public int TransformBlock (byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
			{
				if (inputBuffer == null)
					throw new ArgumentNullException ("inputBuffer");

				if (inputOffset < 0 || inputOffset > inputBuffer.Length)
					throw new ArgumentOutOfRangeException ("inputOffset");

				if (inputCount < 0 || inputOffset > inputBuffer.Length - inputCount)
					throw new ArgumentOutOfRangeException ("inputCount");

				if (inputCount != 8)
					throw new ArgumentOutOfRangeException ("inputCount", "Can only transform 8 bytes at a time.");

				if (outputBuffer == null)
					throw new ArgumentNullException ("outputBuffer");

				if (outputOffset < 0 || outputOffset > outputBuffer.Length - 8)
					throw new ArgumentOutOfRangeException ("outputOffset");

				return engine.ProcessBlock (inputBuffer, inputOffset, outputBuffer, outputOffset);
			}

			public byte[] TransformFinalBlock (byte[] inputBuffer, int inputOffset, int inputCount)
			{
				if (inputBuffer == null)
					throw new ArgumentNullException ("inputBuffer");

				if (inputOffset < 0 || inputOffset > inputBuffer.Length)
					throw new ArgumentOutOfRangeException ("inputOffset");

View on GitHub (pinned to 9d3859a785)