{"record":{"id":"9a8f7ff156213453","repo":"Kareadita/Kavita","slug":"image-element-does-not-have-a-valid-source-attribu","errorCode":null,"errorMessage":"Image element does not have a valid source attribute","messagePattern":"Image element does not have a valid source attribute","errorType":"exception","errorClass":"KavitaException","httpStatus":null,"severity":"warning","filePath":"Kavita.Services/BookService.cs","lineNumber":1268,"sourceCode":"\n            if (images == null || images.Count == 0)\n            {\n                throw new KavitaException(\"No images found on the specified page\");\n            }\n\n            if (bookmarkDto.ImageOffset >= images.Count)\n            {\n                throw new KavitaException($\"Image index {bookmarkDto.ImageOffset} is out of range. Page has {images.Count} images\");\n            }\n\n            var targetImage = images[bookmarkDto.ImageOffset];\n\n            // Get the image source attribute\n            var srcAttributeName = GetImageSrcAttributeName(targetImage);\n\n            if (string.IsNullOrEmpty(srcAttributeName))\n            {\n                throw new KavitaException(\"Image element does not have a valid source attribute\");\n            }\n\n            var imageSource = targetImage.Attributes[srcAttributeName].Value;\n\n            // Clean and get the correct key for the image\n            var imageKey = CleanContentKeys(GetKeyForImage(book, imageSource));\n\n            // Check if it's an external URL\n            if (imageKey.StartsWith(\"http\"))\n            {\n                throw new KavitaException(\"Cannot copy external images\");\n            }\n\n            // Get the image file from the epub\n\n            if (!book.Content.Images.TryGetLocalFileRefByKey(imageKey, out var imageFile))\n            {\n                throw new KavitaException($\"Image file not found in epub: {imageKey}\");","sourceCodeStart":1250,"sourceCodeEnd":1286,"githubUrl":"https://github.com/Kareadita/Kavita/blob/9c3e5400007f8a0282f7d883f2ad5e71716e514d/Kavita.Services/BookService.cs#L1250-L1286","documentation":"Thrown by BookService.CopyImageToTempFromBook (line 1268) when the selected <img>/<image> node has neither a 'src' attribute nor an 'xlink:href' attribute (the only two src attribute names GetImageSrcAttributeName recognizes). The image element exists but Kavita cannot determine its source.","triggerScenarios":"An epub page whose image element uses a non-standard attribute (e.g. data-src, poster) or a malformed/empty image tag with no src/xlink:href.","commonSituations":"Hand-authored or converter-produced epub with lazy-loading 'data-src' attributes; SVG <image> missing xlink:href.","solutions":["Repair the epub so image elements use standard src (or xlink:href for SVG image).","Extend GetImageSrcAttributeName to recognize additional common attributes (data-src) if appropriate for your corpus."],"exampleFix":"// before\nprivate static string? GetImageSrcAttributeName(HtmlNode targetImage) {\n    if (targetImage.Attributes[\"src\"] != null) return \"src\";\n    if (targetImage.Attributes[\"xlink:href\"] != null) return \"xlink:href\";\n    return null;\n}\n\n// after — also accept lazy-load variants\nif (targetImage.Attributes[\"data-src\"] != null) return \"data-src\";","handlingStrategy":"validation","validationCode":"// Pre-check the image element's source attribute on the client\nconst hasSrc = img.hasAttribute('src') || img.hasAttribute('xlink:href');\nif (!hasSrc) { /* don't offer copy-image for this element */ }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Repair epubs whose image elements use non-standard src attributes (data-src, etc.).","Extend GetImageSrcAttributeName only if your corpus consistently uses an alternative attribute."],"tags":["book-reader","epub","bookmark","validation"],"backgroundTag":null,"analyzedSha":"9c3e5400007f8a0282f7d883f2ad5e71716e514d","analyzedAt":"2026-08-13T19:06:05.897Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}