{"record":{"id":"21bcb2442835527a","repo":"Kareadita/Kavita","slug":"name-must-be-set","errorCode":null,"errorMessage":"Name must be set","messagePattern":"Name must be set","errorType":"exception","errorClass":"KavitaException","httpStatus":400,"severity":"warning","filePath":"Kavita.Server/Controllers/FilterController.cs","lineNumber":125,"sourceCode":"    {\n        try\n        {\n            if (string.IsNullOrEmpty(dto.Name)) return BadRequest(\"Name is required\");\n            var encodedString = SmartFilterHelper.Encode(dto);\n            await ValidateAndSaveFilterUpsert(dto.Name!, encodedString, dto.EntityType);\n            return Ok();\n        }\n        catch (KavitaException ex)\n        {\n            return BadRequest(ex.Message);\n        }\n    }\n\n    private async Task ValidateAndSaveFilterUpsert(string filterName, string encodedFilter,  FilterEntityType entityType)\n    {\n        var user = (await unitOfWork.UserRepository.GetUserByIdAsync(UserId, AppUserIncludes.SmartFilters))!;\n\n        if (string.IsNullOrWhiteSpace(filterName)) throw new KavitaException(\"Name must be set\");\n        if (Defaults.DefaultStreams.Any(s => s.Name.Equals(filterName, StringComparison.InvariantCultureIgnoreCase)))\n        {\n            // NOTE: This checks against localization keys (on-deck), so this case will almost never happen\n            throw new KavitaException(\"You cannot use the name of a system provided stream\");\n        }\n\n        var existingFilter = user.SmartFilters.FirstOrDefault(s => s.Name.Equals(filterName, StringComparison.InvariantCultureIgnoreCase));\n        if (existingFilter != null)\n        {\n            // Update the filter\n            existingFilter.Filter = encodedFilter;\n            unitOfWork.AppUserSmartFilterRepository.Update(existingFilter);\n        }\n        else\n        {\n            existingFilter = new AppUserSmartFilter()\n            {\n                Name = filterName,","sourceCodeStart":107,"sourceCodeEnd":143,"githubUrl":"https://github.com/Kareadita/Kavita/blob/9c3e5400007f8a0282f7d883f2ad5e71716e514d/Kavita.Server/Controllers/FilterController.cs#L107-L143","documentation":"Thrown by FilterController.ValidateAndSaveFilterUpsert when the smart-filter name is null, empty, or whitespace. The calling endpoints catch KavitaException and return it as HTTP 400 BadRequest with 'Name must be set'.","triggerScenarios":"POST to a filter upsert endpoint (create/update smart filter, annotation filter) with an empty Name in the DTO, or with whitespace only.","commonSituations":"Frontend submits before the name input is filled; a scripted client omits the name field; trimming turns a spaces-only name into empty.","solutions":["Provide a non-empty, non-whitespace name in the filter upsert request.","Validate the name client-side before enabling submit.","If scripting the API, assert dto.Name is not null/empty before sending."],"exampleFix":"// before\n{ \"name\": \"   \", \"filter\": \"...\" }\n\n// after\n{ \"name\": \"My Reading List\", \"filter\": \"...\" }","handlingStrategy":"validation","validationCode":"if (string.IsNullOrWhiteSpace(dto.Name))\n    return BadRequest(\"Name must be set\");","typeGuard":"static bool IsValidFilterName(string? name)\n    => !string.IsNullOrWhiteSpace(name);","tryCatchPattern":"try { await ValidateAndSaveFilterUpsert(name, enc, type); }\ncatch (KavitaException ex) { return BadRequest(ex.Message); }","preventionTips":["Disable submit until a non-empty name is entered.","Trim and assert non-empty on the client before posting.","Script callers should assert dto.Name is set."],"tags":["filtering","validation","input","smart-filter"],"backgroundTag":null,"analyzedSha":"9c3e5400007f8a0282f7d883f2ad5e71716e514d","analyzedAt":"2026-08-13T19:06:05.897Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}