bitwarden/server · warning · BadRequestException

This request is no longer valid. Make sure to approve the mo

Error message

This request is no longer valid. Make sure to approve the most recent request.

What it means

Thrown as BadRequestException with a custom message (HTTP 400) from ValidateApprovalOfMostRecentAuthRequest, called by PUT /auth-requests/{id} when RequestApproved is true. After confirming the request exists, the method checks whether it is the most recent pending auth request for the same device (matched by RequestDeviceIdentifier). If a newer request exists for the same device, this older one is considered stale and cannot be approved.

Source

Thrown at src/Api/Auth/Controllers/AuthRequestsController.cs:138

    {
        // Get the current auth request to find the device identifier
        var currentAuthRequest = await _authRequestService.GetAuthRequestAsync(id, userId);
        if (currentAuthRequest == null)
        {
            throw new NotFoundException();
        }

        // Get all pending auth requests for this user (returns most recent per device)
        var pendingRequests = await _authRequestRepository.GetManyPendingAuthRequestByUserId(userId);

        // Find the most recent request for the same device
        var mostRecentForDevice = pendingRequests
            .FirstOrDefault(pendingRequest => pendingRequest.RequestDeviceIdentifier == currentAuthRequest.RequestDeviceIdentifier);

        var isMostRecentRequestForDevice = mostRecentForDevice?.Id == id;
        if (!isMostRecentRequestForDevice)
        {
            throw new BadRequestException("This request is no longer valid. Make sure to approve the most recent request.");
        }
    }
}

View on GitHub (pinned to e93b962371)

Solutions

  1. Call GET /auth-requests/pending to find the most recent request for the device and approve that one instead.
  2. Ensure the approving device's UI refreshes the pending list before showing approve/deny buttons.
  3. On the requesting side, avoid creating duplicate auth requests — cancel or wait before retrying.

Example fix

// before: approving an older request that's been superseded
var resp = await client.PutAsJsonAsync($"/auth-requests/{olderId}",
    new AuthRequestUpdateRequestModel { RequestApproved = true }); // 400

// after: approve the most recent pending request for the device
var pending = await client.GetAsync("/auth-requests/pending");
var mostRecent = pending.Items
    .Where(r => r.RequestDeviceIdentifier == targetDevice)
    .OrderByDescending(r => r.CreationDate)
    .First();
var resp = await client.PutAsJsonAsync($"/auth-requests/{mostRecent.Id}",
    new AuthRequestUpdateRequestModel { RequestApproved = true });
Defensive patterns

Strategy: validation

Validate before calling

// Before approving, ensure this is the most recent request for the device
var pending = await client.GetAsync("/auth-requests/pending");
var requestsForDevice = pending.Items
    .Where(r => r.RequestDeviceIdentifier == targetDeviceIdentifier)
    .OrderByDescending(r => r.CreationDate)
    .ToList();
if (requestsForDevice.Count == 0 || requestsForDevice[0].Id != idToApprove) {
    var correctId = requestsForDevice[0]?.Id;
    return Error($"A newer request exists for this device. Approve request {correctId} instead.");
}

Try / catch

try {
    var resp = await client.PutAsJsonAsync($"/auth-requests/{id}",
        new AuthRequestUpdateRequestModel { RequestApproved = true });
    resp.EnsureSuccessStatusCode();
} catch (HttpRequestException ex) when (ex.StatusCode == HttpStatusCode.BadRequest) {
    var body = await ex.Response.Content.ReadAsStringAsync();
    if (body.Contains("most recent request")) {
        // Fetch the most recent pending request for this device and approve that
        var pending = await client.GetAsync("/auth-requests/pending");
        var mostRecent = GetMostRecentForDevice(pending, deviceIdentifier);
        resp = await client.PutAsJsonAsync($"/auth-requests/{mostRecent.Id}",
            new AuthRequestUpdateRequestModel { RequestApproved = true });
    }
}

Prevention

When it happens

Trigger: A device created multiple auth requests in sequence (e.g., the user repeatedly tapped 'approve login'). When the approving device tries to approve an older request, the server rejects it because only the most recent request per device is valid for approval.

Common situations: Requesting device sent multiple login requests rapidly, creating multiple pending entries for the same device identifier. Network retries on the requesting side created duplicate requests. User initiated login on the same device multiple times before approval. The approving device is acting on a notification for an older request while a newer one supersedes it.

Related errors


AI-assisted analysis of bitwarden/server@e93b962371 (2026-08-13). Data as JSON: /api/errors/86b9655df34e7b3a. Report an issue: GitHub.