DEV Community

Cover image for Debugging Astro — Practical Tips & Tricks
Athreya aka Maneshwar
Athreya aka Maneshwar

Posted on

Debugging Astro — Practical Tips & Tricks

Hello, I'm Maneshwar. I'm working on FreeDevTools online currently building *one place for all dev tools, cheat codes, and TLDRs* — a free, open-source hub where developers can quickly find and use tools without any hassle of searching all over the internet.

Debugging in Astro is mostly familiar territory if you’ve worked with web frameworks before, but there are important differences because Astro renders on the server by default.

This guide collects practical, real-world debugging tips so you can find problems faster and with less friction.

Where your console.log() shows up

console.log() is simple and effective — but where you put it matters in Astro.

  • Frontmatter (server)
  ---
  console.log('Hi! I\'m the server. This logs to the terminal where Astro is running.');
  ---
Enter fullscreen mode Exit fullscreen mode

Anything in the frontmatter runs on the server and prints to the terminal running the Astro CLI.

  • <script> in the component (client)
  <script>
    console.log('Hi! I\'m the client. This prints in the browser devtools console.');
  </script>
Enter fullscreen mode Exit fullscreen mode

Code in a <script> tag (module by default) runs in the browser.

  • Framework components (React/Svelte/Vue) These render server-side by default, so console.log() will usually appear in the terminal — but when the component is hydrated on the client (via a client: directive), logs may also appear in the browser console. This helps you compare server render vs hydrated client behavior.

Use the built-in <Debug /> component

Astro ships with a Debug component that outputs values directly into your rendered HTML — great when you want to inspect data without switching between terminal and browser.

---
import { Debug } from 'astro:components';
const sum = (a, b) => a + b;
const answer = sum(2, 4);
---

<!-- All three are equivalent -->
<Debug answer={sum(2, 4)} />
<Debug {{answer: sum(2, 4)}} />
<Debug {answer} />
Enter fullscreen mode Exit fullscreen mode

<Debug /> is particularly handy for templating issues and quick experiments where you need to see the shape of objects in the page source.

Common error messages and fixes

Cannot use import statement outside a module

  • Cause: <script> tags in Astro are modules by default, but adding attributes like is:inline removes that default.
  • Fix: Add type="module" to the <script> tag if you need to use import.

document or window is not defined`

  • Cause: Server-side rendering. document and window don't exist on the server.
  • Fixes:
    • Move browser-only code into a <script> tag in the template (client).
    • In framework components, use lifecycle hooks (useEffect, onMount) and hydrate with a client: directive (e.g. client:load or client:only).
    • Check third-party packages — some require client-only execution.

Expected a default export

  • Cause: Importing or rendering an invalid component (or missing export).
  • Fix: Verify import path, filename/extension, and that the component actually exports correctly. Reproduce in a minimal Astro starter if unsure.

Refused to execute inline script (CSP)

  • Cause: A strict Content Security Policy that blocks inline scripts (Astro emits inline script by default).
  • Fixes:
    • Add script-src: 'unsafe-inline' to CSP (not ideal).
    • Use an integration like astro-shield to generate safe CSP headers.

Common gotchas and quick checks

  • Component not rendering
    • Ensure you imported the component and used the correct import path and file extension (.astro, .svelte, .vue, .mdx, etc.).
  • Component renders but is not interactive
    • If you expect client interactivity, add a client: directive (e.g. client:load, client:idle, client:visible) or use client:only when appropriate.
  • Cannot find package 'X'
    • Some integrations (e.g. @astrojs/react) require installing peer dependencies like react and react-dom.
    • Example: npm install @astrojs/react react react-dom
  • Yarn 2+ (Berry) issues
    • Berry uses Plug'n'Play; set nodeLinker: "node-modules" in .yarnrc.yml if you encounter issues.
  • Monorepo dependency quirks
    • Add Astro-related dependencies to the project package.json, and for some packages add them to vite.ssr.noExternal in astro.config.mjs.
  • Unexpected <style> inclusion
    • Astro bundles styles from any imported component present in the module graph — even if conditionally rendered and not present in final output.

Closing notes

Astro’s server-first model forces you to think intentionally about where code runs — and that distinction makes debugging clearer once you internalize it.

Use console.log() in the right place, lean on <Debug /> for quick inspections, and keep minimal reproductions handy for tricky cases.

FreeDevTools

I’ve been building for FreeDevTools.

A collection of UI/UX-focused tools crafted to simplify workflows, save time, and reduce friction in searching tools/materials.

Any feedback or contributors are welcome!

It’s online, open-source, and ready for anyone to use.

👉 Check it out: FreeDevTools
⭐ Star it on GitHub: freedevtools

Top comments (0)