Fix: Astro.glob() Used Outside of an Astro File

Error message:
Astro.glob() used outside of an Astro file.
Build & Compilation 2025-01-25

What Causes This Error?

This error occurs when you use Astro.glob() in a file that isn’t an .astro file. The Astro global object is only available in .astro components.

The Problem

// src/utils/getPosts.js
// ❌ Astro.glob not available in .js files
export async function getPosts() {
  return await Astro.glob('../content/blog/*.md');
}
// src/lib/content.ts
// ❌ Astro.glob not available in .ts files
const posts = await Astro.glob('./posts/*.md');

The Fix

Use import.meta.glob Instead

// src/utils/getPosts.js
// ✅ import.meta.glob works in any file
export async function getPosts() {
  const posts = import.meta.glob('../content/blog/*.md', { eager: true });
  return Object.values(posts);
}

Or Use Content Collections

// src/utils/getPosts.ts
import { getCollection } from 'astro:content';

// ✅ Content collections work anywhere
export async function getPosts() {
  return await getCollection('blog');
}

Common Scenarios

Helper Functions

// src/utils/content.js

// ❌ Won't work
export async function getAllPosts() {
  return await Astro.glob('../posts/*.md');
}

// ✅ Works - use import.meta.glob
export function getAllPosts() {
  const posts = import.meta.glob('../posts/*.md', { eager: true });
  return Object.values(posts).map(post => post.default);
}

In JavaScript/TypeScript Files

// src/lib/images.ts

// ❌ Astro object not available
const images = await Astro.glob('../assets/*.jpg');

// ✅ Use import.meta.glob
const imageModules = import.meta.glob('../assets/*.jpg', {
  eager: true,
  query: '?url',
  import: 'default',
});

export const images = Object.values(imageModules);

Use in .astro Files

---
// src/pages/blog/index.astro
// ✅ Astro.glob works in .astro files
const posts = await Astro.glob('../content/blog/*.md');
---

{posts.map(post => (
  <article>
    <h2>{post.frontmatter.title}</h2>
  </article>
))}

Passing Glob Results as Props

---
// src/pages/index.astro
// Glob in .astro file
const posts = await Astro.glob('./posts/*.md');
---

<!-- Pass to components -->
<PostList posts={posts} />
---
// src/components/PostList.astro
// Receive as props instead of globbing
const { posts } = Astro.props;
---

<ul>
  {posts.map(post => <li>{post.frontmatter.title}</li>)}
</ul>

import.meta.glob Options

// Non-eager (lazy loading)
const modules = import.meta.glob('./posts/*.md');
// Returns { './posts/a.md': () => import('./posts/a.md') }

// Eager (immediate loading)
const modules = import.meta.glob('./posts/*.md', { eager: true });
// Returns { './posts/a.md': { default: ..., frontmatter: ... } }

// Import specific export
const modules = import.meta.glob('./posts/*.md', {
  import: 'frontmatter',
  eager: true,
});
// src/content/config.ts
import { defineCollection, z } from 'astro:content';

const blog = defineCollection({
  type: 'content',
  schema: z.object({
    title: z.string(),
    date: z.date(),
  }),
});

export const collections = { blog };
// src/utils/posts.ts
import { getCollection } from 'astro:content';

// ✅ Works anywhere
export async function getBlogPosts() {
  return await getCollection('blog');
}

Comparison

FeatureAstro.glob()import.meta.globContent Collections
Works in .astro
Works in .js/.ts
Type safety
Schema validation
RecommendedLegacyFor assetsFor content

Quick Checklist

  • Astro.glob() only works in .astro files
  • Use import.meta.glob() in JS/TS files
  • Use Content Collections for typed content
  • Pass glob results as props to components
  • Consider migrating from Astro.glob to Content Collections