Kareadita/Kavita · warning · KavitaException
collection-tag-title-required
Error message
collection-tag-title-required
What it means
Thrown by UpdateTag when the title, after trimming, is null or empty. The check 'string.IsNullOrEmpty(title)' fires after 'dto.Title.Trim()'. This is pure input validation — the collection exists (checked before) and ownership passed, but the submitted title is blank.
Source
Thrown at Kavita.Services/CollectionTagService.cs:41
var collectionTag = await unitOfWork.CollectionTagRepository.GetCollectionAsync(tagId, ct: ct);
if (collectionTag == null) return true;
user.Collections.Remove(collectionTag);
if (!unitOfWork.HasChanges()) return true;
return await unitOfWork.CommitAsync(ct);
}
public async Task<bool> UpdateTag(AppUserCollectionDto dto, int userId, CancellationToken ct = default)
{
var existingTag = await unitOfWork.CollectionTagRepository.GetCollectionAsync(dto.Id, ct: ct);
if (existingTag == null) throw new KavitaException("collection-doesnt-exist");
if (existingTag.AppUserId != userId) throw new KavitaException("access-denied");
var title = dto.Title.Trim();
if (string.IsNullOrEmpty(title)) throw new KavitaException("collection-tag-title-required");
// Ensure the title doesn't exist on the user's account already
if (!title.Equals(existingTag.Title) && await unitOfWork.CollectionTagRepository.CollectionExists(dto.Title, userId, ct))
throw new KavitaException("collection-tag-duplicate");
existingTag.Items ??= [];
if (existingTag.Source == ScrobbleProvider.Kavita)
{
existingTag.Title = title;
existingTag.NormalizedTitle = dto.Title.ToNormalized();
}
var roles = await unitOfWork.UserRepository.GetRoles(userId, ct);
if (roles.Contains(PolicyConstants.AdminRole) || roles.Contains(PolicyConstants.PromoteRole))
{
existingTag.Promoted = dto.Promoted;
}
existingTag.CoverImageLocked = dto.CoverImageLocked;View on GitHub (pinned to 9c3e540000)
Solutions
- Add client-side validation to prevent empty title submissions (required attribute on the input field)
- Validate the title is non-empty in the controller before calling UpdateTag
- Ensure the DTO has [Required] data annotation on the Title property
Example fix
// Add DTO validation:
// public class AppUserCollectionDto
// {
// [Required(ErrorMessage = "Title is required")]
// [MinLength(1)]
// public string Title { get; set; } = string.Empty;
// } Defensive patterns
Strategy: validation
Validate before calling
// Validate title before calling UpdateTag:
// var trimmedTitle = dto.Title?.Trim();
// if (string.IsNullOrEmpty(trimmedTitle)) {
// return BadRequest("Collection title is required");
// } Try / catch
// try {
// await collectionTagService.UpdateTag(dto, userId, ct);
// } catch (KavitaException ex) when (ex.Message == "collection-tag-title-required") {
// return BadRequest(new { error = "A non-empty title is required." });
// } Prevention
- Add [Required] and [MinLength(1)] data annotations on the DTO Title property
- Implement client-side form validation to prevent empty submissions
- Disable the submit button until the title field has non-whitespace content
When it happens
Trigger: User submits an empty title or a title consisting only of whitespace characters; form validation on the client side failed to prevent an empty submission; API call constructed programmatically with an empty title field.
Common situations: Client-side validation was bypassed or is incomplete; user cleared the title field and submitted without the UI catching it; automated/scripted requests with malformed payloads.
Related errors
- invalid-payload
- collection-tag-duplicate
- {comparison} is not applicable for {fieldName}
- Name must be set
- You cannot use the name of a system provided stream
AI-assisted analysis of Kareadita/Kavita@9c3e540000 (2026-08-13).
Data as JSON: /api/errors/64f704d20fc532fa.
Report an issue: GitHub.