{"record":{"id":"7f740e6bb939b9c7","repo":"Kareadita/Kavita","slug":"invalid-base64-string","errorCode":null,"errorMessage":"Invalid Base64 string","messagePattern":"Invalid Base64 string","errorType":"exception","errorClass":"KavitaException","httpStatus":null,"severity":"error","filePath":"Kavita.Services/ImageService.cs","lineNumber":418,"sourceCode":"\n    /// <inheritdoc />\n    public string CreateThumbnailFromBase64(string encodedImage, string fileName, EncodeFormat encodeFormat,\n        int thumbnailWidth = ThumbnailWidth, int thumbnailHeight = ThumbnailHeight, string? targetDirectory = null)\n    {\n        // TODO: This code has no concept of cropping nor Thumbnail Size\n        try\n        {\n            targetDirectory ??= directoryService.CoverImageDirectory;\n            using var thumbnail = Image.ThumbnailBuffer(Convert.FromBase64String(encodedImage), thumbnailWidth, height: thumbnailHeight);\n\n            fileName += encodeFormat.GetExtension();\n            thumbnail.WriteToFile(directoryService.FileSystem.Path.Join(targetDirectory, fileName));\n\n            return fileName;\n        }\n        catch (FormatException e)\n        {\n            throw new KavitaException(\"Invalid Base64 string\", e);\n        }\n        catch (Exception e)\n        {\n            logger.LogError(e, \"Error creating thumbnail from url\");\n        }\n\n        return string.Empty;\n    }\n\n    /// <inheritdoc />\n    public string CreateThumbnailFromFile(string sourceFile, string fileName, EncodeFormat encodeFormat,\n        int thumbnailWidth = 320, int thumbnailHeight = 455, string? targetDirectory = null)\n    {\n        try\n        {\n            targetDirectory ??= directoryService.CoverImageDirectory;\n            using var thumbnail = Image.Thumbnail(sourceFile, thumbnailWidth, thumbnailHeight);\n","sourceCodeStart":400,"sourceCodeEnd":436,"githubUrl":"https://github.com/Kareadita/Kavita/blob/9c3e5400007f8a0282f7d883f2ad5e71716e514d/Kavita.Services/ImageService.cs#L400-L436","documentation":"Thrown by ImageService.CreateThumbnailFromBase64 when Convert.FromBase64String(encodedImage) raises a FormatException — i.e. the input is not a valid Base64 group of 4-char blocks. The FormatException is wrapped in a KavitaException so the UI sees a friendly message instead of a raw framework error. Any non-FormatException (e.g. bad image bytes) is swallowed and logged, returning an empty string instead.","triggerScenarios":"Posting a cover/thumbnail upload whose payload is not padded/encoded correctly: missing Base64 padding ('='), contains characters outside [A-Za-z0-9+/=], length not a multiple of 4, or the data-URL prefix 'data:image/png;base64,' was left attached to the string passed to Convert.FromBase64String.","commonSituations":"Frontend sends the raw data-URI scheme prefix with the Base64 body; a copy-paste truncates the trailing padding; an image was encoded as Base64URL (- _ instead of + /) rather than standard Base64; whitespace or a newline inserted mid-string.","solutions":["Strip any data-URI prefix before calling CreateThumbnailFromBase64 (split on ',' and use the second part).","Validate the string with a regex like ^[A-Za-z0-9+/]+={0,2}$ and length % 4 == 0 before posting.","If your source is Base64URL, convert it to standard Base64 (replace - with +, _ with /) and re-pad to a multiple of 4.","Re-encode the original bytes with Convert.ToBase64String on the server or FileReader.readAsDataURL on the client to guarantee format."],"exampleFix":"// before\nvar name = imageService.CreateThumbnailFromBase64(rawDataUri, \"cover\", format);\n\n// after\nvar b64 = rawDataUri.Contains(',') ? rawDataUri.Split(',')[1] : rawDataUri;\nb64 = b64.Trim().Replace('-', '+').Replace('_', '/');\nb64 = b64.PadRight((b64.Length + 3) / 4 * 4, '=');\nvar name = imageService.CreateThumbnailFromBase64(b64, \"cover\", format);","handlingStrategy":"validation","validationCode":"static readonly Regex B64 = new(@\"^[A-Za-z0-9+/]+={0,2}$\", RegexOptions.Compiled);\n\nbool TryNormalizeBase64(string raw, out string b64)\n{\n    b64 = raw.Contains(',') ? raw.Split(',', 2)[1] : raw;\n    b64 = b64.Trim().Replace('-', '+').Replace('_', '/');\n    b64 = b64.PadRight((b64.Length + 3) / 4 * 4, '=');\n    return B64.IsMatch(b64) && b64.Length % 4 == 0;\n}\n\nif (!TryNormalizeBase64(payload, out var clean))\n    return BadRequest(\"Invalid Base64 image.\");","typeGuard":"bool IsBase64Image(string raw)\n{\n    var body = raw.Contains(',') ? raw.Split(',', 2)[1] : raw;\n    body = body.Trim().Replace('-', '+').Replace('_', '/');\n    body = body.PadRight((body.Length + 3) / 4 * 4, '=');\n    try { Convert.FromBase64String(body); return true; }\n    catch { return false; }\n}","tryCatchPattern":"try { name = imageService.CreateThumbnailFromBase64(clean, fn, fmt); }\ncatch (KavitaException ex) when (ex.Message == \"Invalid Base64 string\")\n{ /* reject upload with a clear 'image encoding invalid' message */ }","preventionTips":["Always strip the data-URI scheme prefix on the client before posting.","Send Base64, not Base64URL, for image uploads.","Validate length is a multiple of 4 and characters are within the Base64 alphabet."],"tags":["base64","image-upload","thumbnail","input-validation"],"backgroundTag":null,"analyzedSha":"9c3e5400007f8a0282f7d883f2ad5e71716e514d","analyzedAt":"2026-08-13T19:06:05.897Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}