Problem
Last Friday, while working on my Kanji Sensei App I encountered an issue where my PDF ( pdf-lib) preview iFrame worked perfectly on localhost, but completely failed in production.
In Chrome devtools I did observe, see below code block, and at first thought I suspected it be some CSP issue, but that wasn’t the case.
Uncaught (in promise) TypeError: Cannot read properties of null (reading 'style')
at Gu (kanji-sensei.astro_astro_type_script_index_0_lang.C-pL7it-.js:58:2649)
at kanji-sensei.astro_astro_type_script_index_0_lang.C-pL7it-.js:58:2719
Troubleshooting
I kept staring at my click handler, but I could not see the issue what was wrong. Convinced something was wrong there and yet still in doubt. For sanity, I even asked AI to double‑check it and everything looked fine.
Below the relevant part:
// 3. Click Handler
let currentPdfUrl = null;
btn.addEventListener("click", async () => {
const data = window.currentKanji;
if (!data) return;
// 3.1 Generate PDF bytes
const pdfBytes = await generateKanjiPDF(data);
const blob = new Blob([pdfBytes], { type: "application/pdf" });
// 3.2 Clean up previous URL to prevent memory leaks
if (currentPdfUrl) URL.revokeObjectURL(currentPdfUrl);
currentPdfUrl = URL.createObjectURL(blob);
// 3.3 Inject the iframe in container
const container = document.getElementById("pdf-container");
if (container) {
container.innerHTML = `
<iframe
id="pdf-preview"
src="${currentPdfUrl}"
style="display: block; width: 100%; height: 500px;"
class="mt-4 border rounded">
</iframe>`;
setTimeout(() => {
const preview = document.getElementById("pdf-preview");
preview?.scrollIntoView({ behavior: "smooth" });
}, 0);
}
// 4. Trigger the download
const link = document.createElement("a");
link.href = currentPdfUrl;
link.download = `${data.kanji}-practice.pdf`;
link.click();
});
Everything looked correct, yet still no preview in production I still could not find it and started playing with my mousewheel, up and down, up and down. While scrolling up and down the page, I suddenly remembered something……I deactivated iFrame to show up on mobile.
Culprit
if (!isMobile) {
const preview = document.getElementById("pdf-preview");
preview.style.display = "block";
preview.src = currentPdfUrl;
preview.scrollIntoView({ behavior: "smooth" });
} else {
// Optioneel: Aangezien geen preview op mobiel, een kleine toast
console.log("Mobile detected: skipping preview, starting download.");
}
In production, due to timing differences, the iframe did not exist yet when this code ran, which explains:
Uncaught (in promise) TypeError: Cannot read properties of null (reading 'style')
Solution
Simply guard against NULL:
if (preview) {}
like so:
if (!isMobile) {
const preview = document.getElementById("pdf-preview");
if (preview) {
preview.style.display = "block";
preview.src = currentPdfUrl;
preview.scrollIntoView({ behavior: "smooth" });
}
} else {
// Optioneel: Aangezien geen preview op mobiel, een kleine toast
console.log("Mobile detected: skipping preview, starting download.");
}
After the implementation…it worked in production!
Lesson Learned
- Production behaves differently from localhost, especially with DOM timing.
- Never assume an element exists just because it “always did” during development.
- Features disabled for mobile can quietly affect desktop logic if you forget they’re there.
- A simple if (element) guard can prevent runtime errors that only appear in optimized builds.
- Error messages are usually telling the truth, if it says null, it’s probably null.