bitwarden/server · error · BadRequestException

Could not locate send

Error message

Could not locate send

What it means

Thrown as BadRequestException (HTTP 400) from POST /sends/access/ when the Send referenced by the JWT SendId claim cannot be found in the repository. The endpoint requires the 'Send' policy (a valid access token issued for that send), yet the underlying record is gone. A 400 (not 404) is returned because the access token is internally inconsistent with server state.

Source

Thrown at src/Api/Tools/Controllers/SendsController.cs:146

        var sends = await _sendOwnerQuery.GetOwned(User);
        var responses = sends.Select(s => new SendResponseModel(s));
        var result = new ListResponseModel<SendResponseModel>(responses);

        return result;
    }

    [Authorize(Policy = Policies.Send)]
    [HttpPost("access/")]
    [ProducesResponseType<SendAccessResponseModel>(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> AccessUsingAuth()
    {
        var guid = User.GetSendId();
        var send = await _sendRepository.GetByIdAsync(guid);
        if (send == null)
        {
            throw new BadRequestException("Could not locate send");
        }

        if (!INonAnonymousSendCommand.SendCanBeAccessed(send))
        {
            throw new NotFoundException();
        }

        var sendResponse = new SendAccessResponseModel(send);
        if (send.UserId.HasValue && !send.HideEmail.GetValueOrDefault())
        {
            var creator = await _userService.GetUserByIdAsync(send.UserId.Value);
            sendResponse.CreatorIdentifier = creator.Email;
        }

        /*
         * AccessCount is incremented differently depending on Send type:
         * - Text and Item Sends are incremented at every access
         * - File Sends are incremented only when the file is downloaded

View on GitHub (pinned to e93b962371)

Solutions

  1. Have the recipient request a new Send / access link from the owner.
  2. Confirm the Send still exists by having the owner check GET /sends/{id}.
  3. Check the deletion date / expiration has not elapsed server-side.
  4. Clear cached client Send tokens and re-authenticate the access flow.

Example fix

// before
var send = await _sendRepository.GetByIdAsync(guid);
if (send == null) throw new BadRequestException("Could not locate send");

// after: surface a clearer access-state error to the client
if (send == null) throw new NotFoundException(); // 404 'Resource not found.'
Defensive patterns

Strategy: try-catch

Try / catch

try {
    var resp = await client.PostAsync("sends/access/", accessContent);
    resp.EnsureSuccessStatusCode();
} catch (HttpRequestException ex) when (ex.StatusCode == HttpStatusCode.BadRequest) {
    // The Send no longer exists; prompt the user to request a new link.
    ShowUser("This Send is no longer available. Please request a new link.");
}

Prevention

When it happens

Trigger: POST /sends/access/ with a valid Send access token whose SendId points to a Send that was deleted, purged by the deletion-date background job, or never existed (token issued against stale/local data).

Common situations: Recipient opened a Send link after the sender deleted it or after it passed its deletion date; client cached an old access token; the Send was removed by an admin; clock skew caused the deletion job to run early.

Related errors


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