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
- Route text/item Sends to POST /sends and file Sends to POST /sends/file/v2.
- Ensure model.Type == SendType.File (value 1) before calling the file endpoint.
- Validate the client's Send-type selection maps to the correct endpoint.
- 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
- Centralize endpoint selection by Send type in the client SDK.
- Add a unit test asserting text Sends never hit the file endpoint.
- Serialize the Type enum explicitly to avoid default-0 drift.
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
- Invalid content. File size hint is required.
- Max file size is {SendFileSettingHelper.MAX_FILE_SIZE_READAB
- File metadata is required for file sends.
- Could not locate send
- Email verified Sends require a premium membership
AI-assisted analysis of bitwarden/server@e93b962371 (2026-08-13).
Data as JSON: /api/errors/13f44e623256879c.
Report an issue: GitHub.