jstedfast/MailKit · error · ArgumentOutOfRangeException

index

Error message

index

What it means

MailFolder.MoveToAsync (int index, ...) validates that the message index is within [0, Count) before delegating to the multi-message MoveToAsync. An out-of-range index throws ArgumentOutOfRangeException for 'index'. MailKit throws this rather than letting an invalid UID/index reach the IMAP server.

Solutions

  1. Check the index against the current folder.Count before calling (and re-open/Refresh the folder if it may be stale).
  2. Prefer MoveToAsync (IList<int> ids, ...) only after re-validating against the live folder, or use UIDs via UniqueId-based move APIs to avoid index staleness.
  3. Catch ArgumentOutOfRangeException and treat it as 'message no longer exists', then refresh the folder summary.
  4. After expunges by any client, call folder.Refresh (folder.Summary, cancellationToken) to update Count.

Example fix

// before
await folder.MoveToAsync (index, trash); // index may be stale

// after
if (index >= 0 && index < folder.Count)
    await folder.MoveToAsync (index, trash);
else {
    await folder.CloseAsync (false, ct);
    await folder.OpenAsync (FolderAccess.ReadWrite, ct); // refresh
}
Defensive patterns

Strategy: validation

Validate before calling

if (folder.IsOpen == false)
    await folder.OpenAsync (FolderAccess.ReadWrite);
if (index < 0 || index >= folder.Count)
    return; // or refresh and re-map index

Type guard

bool ValidIndex (IMailFolder folder, int index) => index >= 0 && index < folder.Count;

Try / catch

try {
    await folder.MoveToAsync (index, trash, cancellationToken);
} catch (ArgumentOutOfRangeException) {
    await folder.CloseAsync (false, cancellationToken);
    await folder.OpenAsync (FolderAccess.ReadWrite, cancellationToken);
    // re-map or skip: the message was likely expunged
}

Prevention

When it happens

Trigger: Calling folder.MoveToAsync (i, destination) where i < 0 or i >= folder.Count — e.g. a stale index after messages were expunged, or indexing past the end of the folder.

Common situations: Caching indexes from a previous session while other clients expunged messages; iterating with an old Count; confusing message indexes with UIDs; using an index from a different folder.

Related errors


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

Appendix: source

Thrown at MailKit/MailFolder.cs:4401

		/// <exception cref="FolderNotOpenException">
		/// The folder is not currently open in read-write 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>
		/// <exception cref="ProtocolException">
		/// The server's response contained unexpected tokens.
		/// </exception>
		/// <exception cref="CommandException">
		/// The command failed.
		/// </exception>
		public virtual Task MoveToAsync (int index, IMailFolder destination, CancellationToken cancellationToken = default)
		{
			if (index < 0 || index >= Count)
				throw new ArgumentOutOfRangeException (nameof (index));

			return MoveToAsync (new [] { index }, destination, cancellationToken);
		}

		/// <summary>
		/// Move the specified messages to the destination folder.
		/// </summary>
		/// <remarks>
		/// Moves the specified messages to the destination folder.
		/// </remarks>
		/// <param name="indexes">The indexes of the messages to move.</param>
		/// <param name="destination">The destination folder.</param>
		/// <param name="cancellationToken">The cancellation token.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="indexes"/> is <see langword="null" />.</para>
		/// <para>-or-</para>
		/// <para><paramref name="destination"/> is <see langword="null" />.</para>
		/// </exception>

View on GitHub (pinned to 9d3859a785)