komal.nakrani
Browse Themes
ThemesCategoriesDocsBlogTips & Tricks
Routing••By Komal Nakrani

Fix: Unavailable Astro Global in getStaticPaths()

Unavailable Astro global in getStaticPaths(): it runs before any page exists, so Astro.url and Astro.props don't exist. Use imports or the page body.

#Astro#Errors#getStaticPaths

Astro shows “Unavailable Astro global in getStaticPaths()” when code inside getStaticPaths() reads Astro.something, such as Astro.url, Astro.props, Astro.params or Astro.request. The message: “The Astro global is not available in this scope.” getStaticPaths() runs once, before any page is rendered, to decide which pages exist, so there is no current page, URL or request yet. Move that logic into the page body, or use the arguments getStaticPaths() receives.

Key Takeaways

  • getStaticPaths() runs in isolation, before rendering.
  • It receives paginate (and, in recent versions, routePattern) as arguments, not Astro.
  • Values you need there should come from imports or config.
  • Code that needs the current page belongs in the frontmatter after getStaticPaths().

Wrong

---
export async function getStaticPaths() {
  const base = Astro.url.origin;                 // not available
  const posts = await getCollection('blog');
  return posts.map((post) => ({
    params: { slug: post.id },
    props: { post, canonical: `${base}/blog/${post.id}/` },
  }));
}
---

Right: compute per page in the body

---
export async function getStaticPaths() {
  const posts = await getCollection('blog');
  return posts.map((post) => ({ params: { slug: post.id }, props: { post } }));
}

const { post } = Astro.props;
const canonical = new URL(Astro.url.pathname, Astro.site);
---

The frontmatter after getStaticPaths() runs once per generated page, with Astro fully available.

Right: import what you need

Site-wide values like the domain belong in config or a data module:

// src/data/site.ts
export const SITE_URL = 'https://www.example.com';
import { SITE_URL } from '../../data/site';

export async function getStaticPaths() {
  // SITE_URL is a normal import, available here
}

Also not available: top-level variables

getStaticPaths() can’t read variables defined elsewhere in the frontmatter either, because Astro extracts and runs it separately:

---
const tags = ['astro', 'css'];   // not visible inside getStaticPaths

export async function getStaticPaths() {
  const tags = ['astro', 'css']; // define it inside, or import it
  return tags.map((tag) => ({ params: { tag } }));
}
---

What it does receive

export const getStaticPaths = (async ({ paginate }) => {
  const posts = await getCollection('blog');
  return paginate(posts, { pageSize: 10 });
}) satisfies GetStaticPaths;

The Astro routing guide covers pagination and params, and canonical URLs in Astro shows the canonical pattern above. Related: invalid value returned from getStaticPaths(). See the routing reference.

FAQ

Can I use Astro.site in getStaticPaths()?

No. Import the value from a shared module instead, or compute URLs in the page body where Astro.site is available.

Why does Astro run getStaticPaths() separately?

It needs the full list of pages before rendering any of them, and it runs it once per route rather than once per page.