OrchardCMS/OrchardCore · error · ArgumentException

code cannot be null or empty.

Error message

code cannot be null or empty.

What it means

Thrown by UserStore.RedeemCodeAsync when the recovery code argument is null or whitespace. Two-factor recovery codes are stored merged with ';' separators and matched exactly, so a blank code can never be valid and is rejected up front with ArgumentException.

Solutions

  1. Validate the code is non-empty before calling (string.IsNullOrWhiteSpace check) and return a validation message instead.
  2. Require the code field in the login form/API model ([Required], NotEmpty).
  3. Catch ArgumentException and convert it to a failed-login response.
  4. Trim and normalize user input before comparison.

Example fix

// before
var ok = await _userManager.RedeemTwoFactorRecoveryCodeAsync(user, code);
// after
if (string.IsNullOrWhiteSpace(code)) { ModelState.AddModelError(nameof(code), "A recovery code is required."); return View(); }
var ok = await _userManager.RedeemTwoFactorRecoveryCodeAsync(user, code.Trim());
Defensive patterns

Strategy: validation

Validate before calling

if (string.IsNullOrWhiteSpace(code)) return false; // or add model error before calling

Type guard

bool IsPlausibleRecoveryCode(string code) => !string.IsNullOrWhiteSpace(code) && code.Length >= 8;

Try / catch

try { var ok = await _userManager.RedeemTwoFactorRecoveryCodeAsync(user, code); }
catch (ArgumentException) { return SignInResult.Failed; }

Prevention

When it happens

Trigger: Calling RedeemCodeAsync (via UserManager.RedeemTwoFactorRecoveryCodeAsync) with an empty or whitespace-only code from a form; a user submitting the recovery-code field blank.

Common situations: Two-factor login pages without client-side validation; API clients sending empty code fields; automation scripts with unset variables.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of OrchardCMS/OrchardCore@4306c0717f (2026-09-13). Data as JSON: /api/errors/6ef9467b5b080517. Report an issue: GitHub.

Appendix: source

Thrown at src/OrchardCore/OrchardCore.Users.Core/Services/UserStore.cs:848

    #region IUserTwoFactorRecoveryCodeStore
    public Task ReplaceCodesAsync(IUser user, IEnumerable<string> recoveryCodes, CancellationToken cancellationToken)
    {
        ArgumentNullException.ThrowIfNull(user);
        ArgumentNullException.ThrowIfNull(recoveryCodes);

        var mergedCodes = string.Join(";", recoveryCodes);

        return SetTokenAsync(user, InternalLoginProvider, RecoveryCodeTokenName, mergedCodes, cancellationToken);
    }

    public async Task<bool> RedeemCodeAsync(IUser user, string code, CancellationToken cancellationToken)
    {
        ArgumentNullException.ThrowIfNull(user);

        if (string.IsNullOrWhiteSpace(code))
        {
            throw new ArgumentException($"{nameof(code)} cannot be null or empty.");
        }

        var mergedCodes = (await GetTokenAsync(user, InternalLoginProvider, RecoveryCodeTokenName, cancellationToken)) ?? string.Empty;
        var splitCodes = mergedCodes.Split(';');
        if (splitCodes.Contains(code))
        {
            var updatedCodes = new List<string>(splitCodes.Where(s => s != code));
            await ReplaceCodesAsync(user, updatedCodes, cancellationToken);

            return true;
        }

        return false;
    }

    public async Task<int> CountCodesAsync(IUser user, CancellationToken cancellationToken)
    {
        ArgumentNullException.ThrowIfNull(user);

View on GitHub (pinned to 4306c0717f)