withastro/astro · error · Error

Glob patterns cannot start with `/`. Set the `base` option…

Error message

Glob patterns cannot start with `/`. Set the `base` option to a parent directory or use a relative path instead.

What it means

The glob() loader rejects patterns starting with `/` (after stripping any `./` or `!` prefix) because absolute patterns bypass the `base` directory that the loader is built around. The fix is either a relative pattern or an explicit absolute `base`.

Solutions

  1. Drop the leading slash and make the pattern relative: `glob({ pattern: 'blog/**/*.md' })`.
  2. If you truly need an absolute start point, put it in `base` (which accepts a file URL) and keep the pattern relative: `glob({ pattern: '**/*.md', base: new URL('./content/', import.meta.url) })`.

Example fix

// before
const Blog = defineCollection({
  loader: glob({ pattern: '/src/content/blog/**/*.md' }),
});

// after
const Blog = defineCollection({
  loader: glob({ pattern: 'blog/**/*.md' }),
});
Defensive patterns

Strategy: validation

Validate before calling

const isRelativeGlobPattern = (pattern: string): boolean =>
  !pattern.replace(/^(\.\/|!)+/, '').startsWith('/');

if (!isRelativeGlobPattern(pattern)) {
  pattern = pattern.slice(1); // or move the absolute path into `base`
}

Prevention

When it happens

Trigger: `glob({ pattern: '/src/content/blog/**/*.md' })` — developers writing a filesystem-absolute pattern out of habit or copy-pasting one from a bundler config.

Common situations: Porting glob patterns from vite/vitest/tailwind configs where leading slashes are normal; trying to point at content outside the project; mixing up `pattern` and `base` responsibilities.

Related errors


AI-assisted analysis of withastro/astro@e294953aa8 (2026-08-18). Data as JSON: /api/errors/1cb4d1d85718a772. Report an issue: GitHub.

Appendix: source

Thrown at packages/astro/src/content/loaders/glob.ts:93

	}
	return pattern.startsWith(prefix);
}

export const secretLegacyFlag = Symbol('astro.legacy-glob');

/**
 * Loads multiple entries, using a glob pattern to match files.
 * @param pattern A glob pattern to match files, relative to the content directory.
 */

export function glob(globOptions: GlobOptions & { [secretLegacyFlag]?: boolean }): Loader {
	if (checkPrefix(globOptions.pattern, '../')) {
		throw new Error(
			'Glob patterns cannot start with `../`. Set the `base` option to a parent directory instead.',
		);
	}
	if (checkPrefix(globOptions.pattern, '/')) {
		throw new Error(
			'Glob patterns cannot start with `/`. Set the `base` option to a parent directory or use a relative path instead.',
		);
	}

	const isLegacy = !!globOptions[secretLegacyFlag];
	const userGenerateId =
		globOptions?.generateId ?? ((opts: GenerateIdOptions) => generateIdDefault(opts, isLegacy));
	// Coerce to string so numeric ids from YAML don't cause Set strict-equality mismatches
	// against string store keys in the untouched-entries cleanup. See #17624.
	const generateId = (opts: GenerateIdOptions) => String(userGenerateId(opts));

	const fileToIdMap = new Map<string, string>();

	return {
		name: 'glob-loader',
		load: async ({
			config,
			collection,

View on GitHub (pinned to e294953aa8)