bitwarden/server · error · BadRequestException

Invalid content.

Error message

Invalid content.

What it means

Thrown as BadRequestException (HTTP 400) from POST /sends/file/v2 when model.Type is not SendType.File. The file-upload-v2 endpoint only accepts file Sends; submitting a text/item type (or a default/unset Type) is rejected before any storage work begins.

Source

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

        var hasPremium = await _hasPremiumAccessQuery.HasPremiumAccessAsync(userId);

        if (!hasPremium && !string.IsNullOrWhiteSpace(model.Emails))
        {
            throw new BadRequestException("Email verified Sends require a premium membership");
        }

        var send = model.ToSend(userId, _sendAuthorizationService);
        await _nonAnonymousSendCommand.SaveSendAsync(send);
        return new SendResponseModel(send);
    }

    [Authorize(Policies.Application)]
    [HttpPost("file/v2")]
    public async Task<SendFileUploadDataResponseModel> PostFile([FromBody] SendRequestModel model)
    {
        if (model.Type != SendType.File)
        {
            throw new BadRequestException("Invalid content.");
        }

        if (!model.FileLength.HasValue)
        {
            throw new BadRequestException("Invalid content. File size hint is required.");
        }

        if (model.FileLength.Value > Constants.FileSize501mb)
        {
            throw new BadRequestException($"Max file size is {SendFileSettingHelper.MAX_FILE_SIZE_READABLE}.");
        }

        var file = model.File ?? throw new BadRequestException("File metadata is required for file sends.");

        model.ValidateCreation();
        var userId = _userService.GetProperUserId(User) ?? throw new InvalidOperationException("User ID not found");
        var hasPremium = await _hasPremiumAccessQuery.HasPremiumAccessAsync(userId);

View on GitHub (pinned to e93b962371)

Solutions

  1. Route text/item Sends to POST /sends and file Sends to POST /sends/file/v2.
  2. Ensure model.Type == SendType.File (value 1) before calling the file endpoint.
  3. Validate the client's Send-type selection maps to the correct endpoint.
  4. Check JSON serialization includes the Type field with the correct enum value.

Example fix

// before: text send posted to file endpoint
POST /sends/file/v2  body: { "type": 0 /*Text*/, ... } -> 400

// after: use the text endpoint
POST /sends  body: { "type": 0, ... }
Defensive patterns

Strategy: validation

Validate before calling

// Client: route by Send type
var endpoint = model.Type == SendType.File ? "sends/file/v2" : "sends";
await client.PostAsync(endpoint, JsonContent.Create(model));

Type guard

static bool IsFileSend(SendRequestModel m) => m.Type == SendType.File;

Prevention

When it happens

Trigger: POST /sends/file/v2 with a body whose Type is SendType.Text or SendType.Item (or 0/default), e.g. a client routing a text Send to the file endpoint by mistake.

Common situations: Client bug sending text Send data to the file endpoint; mismatched enum serialization (Type omitted or defaulted to 0); copy-paste of the wrong request model; integration test using the wrong endpoint for the payload.

Related errors


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