Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Fix the driver behind crashes, sound loss and screen glitches3Repair Windows errors before they cause bigger problemsSome links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Fix the value passed to doc.addImage() before changing your PDF code. In React, the usual causes are an incomplete FileReader result, a malformed data URL, a raw Base64 payload being treated as a data URL, an unsupported image (or non-image text) encoded as Base64, or format detection that cannot identify the bytes. Inspect the runtime value immediately before the call, wait for image loading to finish, and pass the real format when detection is uncertain.
Start with the exact value sent to addImage
jsPDF’s addImage API accepts several input types, including a Base64 data URL string, an HTMLImageElement, an HTMLCanvasElement, a Uint8Array, and RGBA pixel data. An error such as “Supplied Data is not a valid base64-String” or “AddImage does not support files of type ‘UNKNOWN’” describes the point of failure, not necessarily one root cause.
Log only the type and a short prefix, not the whole image:
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →console.log({
type: typeof imageData,
isString: typeof imageData === "string",
prefix: typeof imageData === "string" ? imageData.slice(0, 40) : undefined,
length: typeof imageData === "string" ? imageData.length : undefined
});
doc.addImage(imageData, "PNG", 10, 10, 100, 60);
At this point verify that the value is the intended image, is nonempty, and has completed loading. A React state value that was set during an asynchronous conversion may still be empty when a click handler reads it.
#1 Best Overall
What a valid image data URL looks like
The documented form is data:[<MIME-type>][;base64],<data>. For a PNG, a complete value starts with data:image/png;base64,; JPEG commonly starts with data:image/jpeg;base64,. Check all three parts:
- An image MIME type follows
data:. - The header contains the
;base64,separator. - The payload after the comma is present and represents image bytes.
function assertImageDataUrl(value) {
if (typeof value !== "string") {
throw new Error("Image data must be a string or another supported input");
}
const match = value.match(/^data:(image/[a-z0-9.+-]+);base64,(.+)$/is);
if (!match || !match[2].trim()) {
throw new Error("Expected a non-empty Base64 image data URL");
}
return { mimeType: match[1].toLowerCase(), payload: match[2] };
}
Do not prepend a second data:image/...;base64, header to a value that already has one. Conversely, if you extracted only the payload after the comma, it is no longer a complete data URL; either rebuild a correctly typed data URL or use another supported input type.
Wait for React’s asynchronous file conversion
FileReader.readAsDataURL() completes later. Calling addImage before its load event fires passes undefined, an empty string, or a stale value. Resolve the read first instead of assuming that a state update has already happened.
import { jsPDF } from "jspdf";
function readAsDataURL(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.onerror = () => reject(reader.error || new Error("File read failed"));
reader.readAsDataURL(file);
});
}
async function addUploadedImageToPdf(file) {
if (!file || !file.type.startsWith("image/")) {
throw new Error("Choose an image file");
}
const imageData = await readAsDataURL(file);
assertImageDataUrl(imageData);
const doc = new jsPDF();
// Match this value to the actual file format.
const format = file.type === "image/jpeg" ? "JPEG" : "PNG";
doc.addImage(imageData, format, 10, 10, 100, 60);
doc.save("image.pdf");
}
A component can call addUploadedImageToPdf(file) directly from an event handler and catch the error for display. If you do store the result in state, trigger PDF generation from an effect or a later action that confirms the state contains the completed string; do not rely on a state setter being synchronous.
Pass the format when recognition is uncertain
The method signature permits an explicit format such as PNG, JPEG, or WEBP. Supplying it helps when a canvas or encoded value cannot be identified automatically, but it does not repair bytes that are not actually an image. The format must match the source.
// Canvas output with an explicit format
a constCanvas = document.querySelector("canvas");
const pngData = a constCanvas.toDataURL("image/png");
doc.addImage(pngData, "PNG", 10, 10, 180, 100);
// JPEG data URL
doc.addImage(jpegDataUrl, "JPEG", 10, 10, 180, 100);
Replace the accidental a constCanvas token in the illustrative snippet with const canvas in your code; the intended call is:
Rank #3
const canvas = document.querySelector("canvas");
const pngData = canvas.toDataURL("image/png");
const doc = new jsPDF();
doc.addImage(pngData, "PNG", 10, 10, 180, 100);
Use the first, corrected snippet in production. The important distinction is that the explicit format is a hint for recognition, not a conversion step.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Check that the Base64 bytes are really an image
Valid Base64 syntax alone proves only that characters can be decoded. It does not prove that the decoded bytes identify PNG, JPEG, WebP, or another format supported by your installed jsPDF version. Common mistakes include encoding a PDF, JSON response, HTML error page, or the text undefined and then passing that string to addImage.
- Inspect the source response’s
Content-Typeand HTTP status before encoding it. - Reject empty files and files whose browser MIME type is not
image/*. - Do not pass a PDF data URL to
addImage; PDF content belongs in a different workflow. - If an API returns a JSON object containing the image, extract the actual field before calling jsPDF.
For binary workflows, avoid unnecessary Base64 conversion and pass a supported Uint8Array when the installed API and image format support it. For DOM-backed content, wait for an HTMLImageElement to finish loading before passing it.
Rank #4
Use a reliable image-loading path for remote URLs
A remote URL is not the same as image bytes. Load it into an image element (with appropriate CORS headers from the server), wait for onload, then draw it to a canvas or pass the loaded element. A failed request can otherwise produce a broken image or an HTML error response.
function loadImage(src) {
return new Promise((resolve, reject) => {
const image = new Image();
image.crossOrigin = "anonymous";
image.onload = () => resolve(image);
image.onerror = () => reject(new Error("Image failed to load"));
image.src = src;
});
}
async function pdfFromUrl(src) {
const image = await loadImage(src);
const doc = new jsPDF();
doc.addImage(image, "JPEG", 10, 10, 180, 100);
doc.save("remote-image.pdf");
}
If the server does not grant CORS access, canvas extraction can be blocked by the browser’s origin policy. Fix the server headers or proxy the image through a trusted backend; changing the Base64 prefix will not solve a tainted canvas.
A systematic debugging checklist
- Record the installed jsPDF version and compare your call with that version’s
addImagedocumentation. - Inspect the value immediately before the call: type, prefix, length, and whether it is the current value.
- For a data URL, verify the MIME type,
;base64,separator, and nonempty payload. - For
FileReader, await theloadevent or a promise wrapper. - Confirm the decoded content is an image, not JSON, PDF, HTML, an error page, or a placeholder string.
- Pass
PNG,JPEG, orWEBPexplicitly when automatic recognition is uncertain. - Try a known-good local image. If it works, the original conversion or network response is the problem.
- Reduce the case to one image and one
addImagecall before reintroducing React state, loops, or uploads.
Common symptoms and fixes
| Symptom | Likely cause | Fix |
|---|---|---|
undefined, empty string, or very short value |
Read or state update has not completed | Await FileReader and inspect the value at call time. |
Value starts with raw characters rather than data:image/ |
Raw Base64 payload passed as a complete data URL | Attach the correct MIME header or use a supported binary input. |
| “UNKNOWN” file type | Missing/incorrect header or unrecognized bytes | Verify the source format and provide the matching format argument. |
| Works for one file, fails for uploads | Some files are not images or are zero bytes | Validate file.type, size, and read errors before conversion. |
| Remote image fails while local image works | Network error, broken URL, or CORS restriction | Check status and CORS headers; wait for onload. |
| Still fails after formatting changes | Version-specific behavior or unsupported format | Check the installed version’s documentation and test a known-good PNG. |
Version and security considerations
Implementation details can differ between releases, so do not assume behavior documented for jsPDF 2.5.1 applies unchanged to another version. Pin and inspect the version actually bundled by your React application.
Best Value
A separate security advisory published on 2025-03-18 identifies a ReDoS issue affecting jsPDF versions through 3.0.0 and lists 3.0.1 or later as patched for that advisory. This is not evidence that the Base64 error is caused by the vulnerability. If untrusted users control image URLs or data, check your dependency lockfile and the current advisory before deploying.
Performance and reliability notes
- Base64 expands binary data, so large images consume more memory than their file size suggests. Resize or compress images before embedding when document size matters.
- Generate one PDF after all required reads have completed rather than racing several asynchronous conversions.
- Keep user-facing errors specific: distinguish “file read failed,” “not an image,” “image failed to load,” and “jsPDF rejected the format.”
- For repeatable output, use a fixed image format and dimensions and avoid relying solely on automatic detection.
Or skip the browser setup
If your goal is a clean screenshot of a web page rather than embedding a user-uploaded image in a client-side PDF, ScreenshotNeo provides a single HTTP request. Its API accepts a URL and returns PNG, JPEG, WebP, or PDF; documentation is at https://screenshotneo.com/docs/.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Cookie and consent banners, newsletter popups, and chat widgets are removed before capture. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers identify the page verdict and billing status. An MCP server supplies take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots each month without a card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallOutdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchFAQ
Can I pass any Base64 string to addImage?
No. The decoded bytes must identify a supported image, and the input must use a supported type or correctly formed data URL.
Why does adding "PNG" sometimes not help?
The format argument guides recognition; it cannot turn JSON, HTML, an empty value, or a different image encoding into PNG bytes.
Should I remove the data:image prefix?
Only when the API path you choose explicitly expects a raw payload. For a data-URL string passed to addImage, keep one correct header and do not duplicate it.
Is this necessarily a React bug?
No. React often exposes the timing problem because file reads and image loads are asynchronous, but the underlying requirement is that jsPDF receive completed, valid image data.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

