{"record":{"id":"1cb4d1d85718a772","repo":"withastro/astro","slug":"glob-patterns-cannot-start-with-set-the-base","errorCode":null,"errorMessage":"Glob patterns cannot start with `/`. Set the `base` option to a parent directory or use a relative path instead.","messagePattern":"Glob patterns cannot start with `/`\\. Set the `base` option to a parent directory or use a relative path instead\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/astro/src/content/loaders/glob.ts","lineNumber":93,"sourceCode":"\t}\n\treturn pattern.startsWith(prefix);\n}\n\nexport const secretLegacyFlag = Symbol('astro.legacy-glob');\n\n/**\n * Loads multiple entries, using a glob pattern to match files.\n * @param pattern A glob pattern to match files, relative to the content directory.\n */\n\nexport function glob(globOptions: GlobOptions & { [secretLegacyFlag]?: boolean }): Loader {\n\tif (checkPrefix(globOptions.pattern, '../')) {\n\t\tthrow new Error(\n\t\t\t'Glob patterns cannot start with `../`. Set the `base` option to a parent directory instead.',\n\t\t);\n\t}\n\tif (checkPrefix(globOptions.pattern, '/')) {\n\t\tthrow new Error(\n\t\t\t'Glob patterns cannot start with `/`. Set the `base` option to a parent directory or use a relative path instead.',\n\t\t);\n\t}\n\n\tconst isLegacy = !!globOptions[secretLegacyFlag];\n\tconst userGenerateId =\n\t\tglobOptions?.generateId ?? ((opts: GenerateIdOptions) => generateIdDefault(opts, isLegacy));\n\t// Coerce to string so numeric ids from YAML don't cause Set strict-equality mismatches\n\t// against string store keys in the untouched-entries cleanup. See #17624.\n\tconst generateId = (opts: GenerateIdOptions) => String(userGenerateId(opts));\n\n\tconst fileToIdMap = new Map<string, string>();\n\n\treturn {\n\t\tname: 'glob-loader',\n\t\tload: async ({\n\t\t\tconfig,\n\t\t\tcollection,","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/withastro/astro/blob/e294953aa8aadd98d5be92e60a03037b05dbdfd4/packages/astro/src/content/loaders/glob.ts#L75-L111","documentation":"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`.","triggerScenarios":"`glob({ pattern: '/src/content/blog/**/*.md' })` — developers writing a filesystem-absolute pattern out of habit or copy-pasting one from a bundler config.","commonSituations":"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.","solutions":["Drop the leading slash and make the pattern relative: `glob({ pattern: 'blog/**/*.md' })`.","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) })`."],"exampleFix":"// before\nconst Blog = defineCollection({\n  loader: glob({ pattern: '/src/content/blog/**/*.md' }),\n});\n\n// after\nconst Blog = defineCollection({\n  loader: glob({ pattern: 'blog/**/*.md' }),\n});","handlingStrategy":"validation","validationCode":"const isRelativeGlobPattern = (pattern: string): boolean =>\n  !pattern.replace(/^(\\.\\/|!)+/, '').startsWith('/');\n\nif (!isRelativeGlobPattern(pattern)) {\n  pattern = pattern.slice(1); // or move the absolute path into `base`\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Do not port absolute patterns from bundler configs into the glob loader.","For absolute locations, use `base: new URL(...)` with a relative pattern."],"tags":["content-collections","glob-loader","path","config"],"backgroundTag":"glob-pattern-misuse","analyzedSha":"e294953aa8aadd98d5be92e60a03037b05dbdfd4","analyzedAt":"2026-08-18T18:48:03.901Z","contentChangedAt":"2026-08-18T18:48:03.901Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}