{"record":{"id":"6f25b01fcfae47d0","repo":"withastro/astro","slug":"no-files-found-matching-globoptions-pattern-i","errorCode":null,"errorMessage":"No files found matching \"${globOptions.pattern}\" in directory \"${relativePath}\"","messagePattern":"No files found matching \"(.+?)\" in directory \"(.+?)\"","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/astro/src/content/loaders/glob.ts","lineNumber":292,"sourceCode":"\t\t\t}\n\n\t\t\tconst filePath = fileURLToPath(baseDir);\n\t\t\tconst relativePath = relative(fileURLToPath(config.root), filePath);\n\n\t\t\tconst exists = existsSync(baseDir);\n\n\t\t\tif (!exists) {\n\t\t\t\t// We warn and don't return because we will still set up the watcher in case the directory is created later\n\t\t\t\tlogger.warn(`The base directory \"${fileURLToPath(baseDir)}\" does not exist.`);\n\t\t\t}\n\n\t\t\tconst files = await tinyglobby(globOptions.pattern, {\n\t\t\t\tcwd: fileURLToPath(baseDir),\n\t\t\t\texpandDirectories: false,\n\t\t\t});\n\n\t\t\tif (exists && files.length === 0) {\n\t\t\t\tlogger.warn(\n\t\t\t\t\t`No files found matching \"${globOptions.pattern}\" in directory \"${relativePath}\"`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tfunction configForFile(file: string) {\n\t\t\t\tconst ext = file.split('.').at(-1);\n\t\t\t\tif (!ext) {\n\t\t\t\t\tlogger.warn(`No extension found for ${file}`);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\treturn entryTypes.get(`.${ext}`);\n\t\t\t}\n\n\t\t\tconst limit = pLimit(10);\n\t\t\tconst skippedFiles: Array<string> = [];\n\n\t\t\tconst contentDir = new URL('content/', config.srcDir);\n","sourceCodeStart":274,"sourceCodeEnd":310,"githubUrl":"https://github.com/withastro/astro/blob/e294953aa8aadd98d5be92e60a03037b05dbdfd4/packages/astro/src/content/loaders/glob.ts#L274-L310","documentation":"The base directory exists but tinyglobby matched zero files for the pattern, so the loader warns and returns early. The most common cause is pattern shape: patterns run with expandDirectories: false, so '*.md' will not descend into subdirectories the way '**/*.md' does.","triggerScenarios":"A pattern missing the '**/' recursive segment; case mismatches on case-sensitive filesystems; a pattern for extensions that do not exist yet in that tree; an empty directory.","commonSituations":"Writing pattern: '*.md' expecting recursion into subfolders; renaming extensions (.markdown vs .md); expecting dotfiles to match a normal pattern.","solutions":["Use recursive patterns like '**/*.md' or an array of patterns","Verify files with the exact case and extension exist under the base directory","Create at least one matching file or fix the base directory if it was also wrong (a separate warning covers that)"],"exampleFix":"// before\nloader: glob({ pattern: '*.md', base: './src/data/blog' })\n\n// after\nloader: glob({ pattern: '**/*.md', base: './src/data/blog' })","handlingStrategy":"validation","validationCode":"// Dry-run the exact pattern to catch zero-match configs before build\nimport { glob } from 'tinyglobby';\nconst matches = await glob(pattern, { cwd: baseDir, expandDirectories: false });\nif (matches.length === 0) {\n  throw new Error(`Pattern ${JSON.stringify(pattern)} matched nothing under ${baseDir} — did you mean '**/*.md'?`);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always include '**/' when entries live in subdirectories; expandDirectories is disabled","Match extension case exactly (.md vs .MD differ on Linux)","Keep a pattern smoke-test script for content configs"],"tags":["astro","content-collections","glob-loader","glob-pattern","empty-matches"],"backgroundTag":"empty-content-collection","analyzedSha":"e294953aa8aadd98d5be92e60a03037b05dbdfd4","analyzedAt":"2026-09-09T03:35:40.650Z","contentChangedAt":"2026-09-09T03:35:40.650Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}