{"record":{"id":"13f44e623256879c","repo":"bitwarden/server","slug":"invalid-content-13f44e","errorCode":null,"errorMessage":"Invalid content.","messagePattern":"Invalid content\\.","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"src/Api/Tools/Controllers/SendsController.cs","lineNumber":254,"sourceCode":"        var hasPremium = await _hasPremiumAccessQuery.HasPremiumAccessAsync(userId);\n\n        if (!hasPremium && !string.IsNullOrWhiteSpace(model.Emails))\n        {\n            throw new BadRequestException(\"Email verified Sends require a premium membership\");\n        }\n\n        var send = model.ToSend(userId, _sendAuthorizationService);\n        await _nonAnonymousSendCommand.SaveSendAsync(send);\n        return new SendResponseModel(send);\n    }\n\n    [Authorize(Policies.Application)]\n    [HttpPost(\"file/v2\")]\n    public async Task<SendFileUploadDataResponseModel> PostFile([FromBody] SendRequestModel model)\n    {\n        if (model.Type != SendType.File)\n        {\n            throw new BadRequestException(\"Invalid content.\");\n        }\n\n        if (!model.FileLength.HasValue)\n        {\n            throw new BadRequestException(\"Invalid content. File size hint is required.\");\n        }\n\n        if (model.FileLength.Value > Constants.FileSize501mb)\n        {\n            throw new BadRequestException($\"Max file size is {SendFileSettingHelper.MAX_FILE_SIZE_READABLE}.\");\n        }\n\n        var file = model.File ?? throw new BadRequestException(\"File metadata is required for file sends.\");\n\n        model.ValidateCreation();\n        var userId = _userService.GetProperUserId(User) ?? throw new InvalidOperationException(\"User ID not found\");\n        var hasPremium = await _hasPremiumAccessQuery.HasPremiumAccessAsync(userId);\n","sourceCodeStart":236,"sourceCodeEnd":272,"githubUrl":"https://github.com/bitwarden/server/blob/e93b962371d80964556f5590c6615f5160a437a1/src/Api/Tools/Controllers/SendsController.cs#L236-L272","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: text send posted to file endpoint\nPOST /sends/file/v2  body: { \"type\": 0 /*Text*/, ... } -> 400\n\n// after: use the text endpoint\nPOST /sends  body: { \"type\": 0, ... }","handlingStrategy":"validation","validationCode":"// Client: route by Send type\nvar endpoint = model.Type == SendType.File ? \"sends/file/v2\" : \"sends\";\nawait client.PostAsync(endpoint, JsonContent.Create(model));","typeGuard":"static bool IsFileSend(SendRequestModel m) => m.Type == SendType.File;","tryCatchPattern":null,"preventionTips":["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."],"tags":["send","send-file","http-400","validation","bitwarden-server"],"backgroundTag":null,"analyzedSha":"e93b962371d80964556f5590c6615f5160a437a1","analyzedAt":"2026-08-13T14:22:19.382Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}