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, notAstro.- 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.