{"record":{"id":"c914fcf67c8fdb93","repo":"bitwarden/server","slug":"file-metadata-is-required-for-file-sends","errorCode":null,"errorMessage":"File metadata is required for file sends.","messagePattern":"File metadata is required for file sends\\.","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"src/Api/Tools/Controllers/SendsController.cs","lineNumber":267,"sourceCode":"    [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\n        if (!hasPremium && !string.IsNullOrWhiteSpace(model.Emails))\n        {\n            throw new BadRequestException(\"Email verified Sends require a premium membership\");\n        }\n\n        var (send, data) = model.ToSend(userId, file.FileName!, _sendAuthorizationService);\n        var uploadUrl = await _nonAnonymousSendCommand.SaveFileSendAsync(send, data, model.FileLength.Value);\n        return new SendFileUploadDataResponseModel\n        {\n            Url = uploadUrl,\n            FileUploadType = _sendFileStorageService.FileUploadType,\n            SendResponse = new SendResponseModel(send)\n        };","sourceCodeStart":249,"sourceCodeEnd":285,"githubUrl":"https://github.com/bitwarden/server/blob/e93b962371d80964556f5590c6615f5160a437a1/src/Api/Tools/Controllers/SendsController.cs#L249-L285","documentation":"Thrown as BadRequestException (HTTP 400) from POST /sends/file/v2 when model.File is null. A File-type Send requires file metadata (name, etc.) at creation; its absence means the client sent an incomplete payload for the declared file type.","triggerScenarios":"POST /sends/file/v2 with Type=File but no File object in the body (model.File == null).","commonSituations":"Client builds the Send request but forgets to attach file metadata; JSON field name mismatch (e.g. 'fileData' vs 'file'); partial/aborted form construction; SDK regression dropping the nested object.","solutions":["Include the File metadata object (with FileName) in the request body.","Confirm the JSON property name matches the server model ('file').","Validate the client builds model.File whenever Type == File before posting.","Update/align the client SDK to the current Send file contract."],"exampleFix":"// before\n{ \"type\": 1, \"fileLength\": 1000, \"key\": \"...\" } // no file -> 400\n\n// after\n{ \"type\": 1, \"fileLength\": 1000, \"file\": { \"fileName\": \"doc.pdf\" }, \"key\": \"...\" }","handlingStrategy":"validation","validationCode":"// Client: ensure file metadata for file Sends\nif (model.Type == SendType.File && model.File is null) {\n    ShowUser(\"File metadata is required for file Sends.\");\n    return;\n}\nawait client.PostAsync(\"sends/file/v2\", JsonContent.Create(model));","typeGuard":"static bool HasFileMetadata(SendRequestModel m) => m.Type != SendType.File || m.File is not null;","tryCatchPattern":null,"preventionTips":["Build the File metadata object whenever Type == File.","Verify JSON property names match the server model.","Add client-side required-field validation before submit."],"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"}