Kareadita/Kavita · error · ArgumentException
Unsupported CBL file extension: {ext}
Error message
Unsupported CBL file extension: {ext} What it means
Thrown by CblParser.Parse when the imported reading-list file has an extension other than .cbl, .xml (both routed to the V1 XML parser) or .json (V2 JSON parser). The parser does no content sniffing; the switch expression rejects anything else with an ArgumentException. This is a hard precondition failure: the file path's extension alone selects the deserializer.
Source
Thrown at Kavita.Services/Helpers/CblParser.cs:34
/// </summary>
public static class CblParser
{
private static readonly JsonSerializerOptions JsonSerializerOptions = new JsonSerializerOptions()
{
PropertyNameCaseInsensitive = true,
};
/// <summary>
/// Auto-detect format by file extension and parse accordingly.
/// </summary>
public static ParsedCblReadingList Parse(string filePath)
{
var ext = Path.GetExtension(filePath).ToLowerInvariant();
return ext switch
{
".cbl" or ".xml" => ParseV1(filePath),
".json" => ParseV2(filePath),
_ => throw new ArgumentException($"Unsupported CBL file extension: {ext}")
};
}
/// <summary>
/// Parse a v1 XML CBL file into the unified model.
/// </summary>
public static ParsedCblReadingList ParseV1(string filePath)
{
var serializer = new XmlSerializer(typeof(CblReadingList));
using var stream = File.OpenRead(filePath);
var cbl = (CblReadingList)serializer.Deserialize(stream);
var result = new ParsedCblReadingList
{
SchemaVersion = 1,
Name = cbl.Name ?? string.Empty,
Summary = cbl.Summary ?? string.Empty,
StartYear = cbl.StartYear,View on GitHub (pinned to 9c3e540000)
Solutions
- Re-save/rename the file so its extension is exactly .cbl, .xml, or .json before uploading.
- Confirm the V1 (XML) vs V2 (JSON) schema of the contents, then pick the matching extension — .cbl/.xml for the XML format, .json for the V2 format.
- If you control the pipeline, strip leading/trailing whitespace and any accidental double dots from the filename upstream of Parse.
- If a new format is legitimately needed, extend the switch in CblParser.Parse with a new arm and a ParseV* method.
Example fix
// before
var result = CblParser.Parse("readinglist.cbz");
// after
var result = CblParser.Parse(Path.ChangeExtension("readinglist.cbz", ".cbl")); Defensive patterns
Strategy: validation
Validate before calling
private static readonly HashSet<string> AllowedCblExtensions = new(StringComparer.OrdinalIgnoreCase) { ".cbl", ".xml", ".json" };
bool IsValidCblFile(string path)
{
var ext = Path.GetExtension(path);
return !string.IsNullOrEmpty(ext) && AllowedCblExtensions.Contains(ext);
}
// before upload
if (!IsValidCblFile(upload.FileName)) return BadRequest("Only .cbl, .xml, .json are accepted."); Type guard
bool IsCblParseable(string path) =>
Path.GetExtension(path)?.ToLowerInvariant() is ".cbl" or ".xml" or ".json"; Try / catch
try { var list = CblParser.Parse(path); }
catch (ArgumentException ex) when (ex.Message.StartsWith("Unsupported CBL file extension"))
{ /* surface 'unsupported file type' to user */ } Prevention
- Restrict the upload <input accept=".cbl,.xml,.json"> so the browser filters first.
- Validate the extension server-side before calling Parse.
- Do not rely on content sniffing — the parser dispatches purely on extension.
When it happens
Trigger: Calling CblParser.Parse(filePath) where Path.GetExtension(filePath).ToLowerInvariant() returns something not in {".cbl", ".xml", ".json"}. Triggered via the CBL import endpoint when a user uploads a .cbz, .txt, .zip, a file with no extension, or a case the ToLowerInvariant did not normalize away from the allowed set.
Common situations: User uploads a ComicBookLover .cbz or a .cbl.txt that an OS/mail client renamed; file saved with a trailing dot or hidden double extension (".json " with whitespace, ".JSON" is fine but ".Json.bak" is not); a reading-list export from another tool uses a proprietary extension.
Related errors
AI-assisted analysis of Kareadita/Kavita@9c3e540000 (2026-08-13).
Data as JSON: /api/errors/0164254f27341b9e.
Report an issue: GitHub.