{"record":{"id":"234ef4eaabe8f970","repo":"withastro/astro","slug":"no-extension-found-for-file","errorCode":null,"errorMessage":"No extension found for ${file}","messagePattern":"No extension found for (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/astro/src/content/loaders/glob.ts","lineNumber":300,"sourceCode":"\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\n\t\t\tconst configFiles = new Set(\n\t\t\t\t['config.js', 'config.ts', 'config.mjs'].map((file) => new URL(file, contentDir).href),\n\t\t\t);\n\n\t\t\tfunction isConfigFile(file: string) {\n\t\t\t\tconst fileUrl = new URL('./' + encodeURI(file), baseDir);\n\t\t\t\treturn configFiles.has(fileUrl.href);\n\t\t\t}","sourceCodeStart":282,"sourceCodeEnd":318,"githubUrl":"https://github.com/withastro/astro/blob/e294953aa8aadd98d5be92e60a03037b05dbdfd4/packages/astro/src/content/loaders/glob.ts#L282-L318","documentation":"configForFile splits a matched path on '.' and takes the last segment to look up the entry type; when that segment is falsy (empty string) there is no extension to map, so the file is skipped with this warning. In practice only degenerate paths reach this branch, since ordinary filenames always yield a non-empty last segment.","triggerScenarios":"A matched path whose last '.'-delimited segment is empty, e.g. a file ending in '.' or a malformed entry returned by the glob.","commonSituations":"Extremely rare; mostly seen with exotic filenames, stray dot-suffixed files, or odd entries emitted by tooling in the content directory.","solutions":["Rename the file to include a real extension","Exclude the file from the glob pattern if it is not content"],"exampleFix":"# before: src/data/blog/draft.\n# after: rename to src/data/blog/draft.md","handlingStrategy":"validation","validationCode":"function hasExtension(file: string): boolean {\n  const ext = file.split('.').at(-1);\n  return typeof ext === 'string' && ext.length > 0;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Enforce real extensions in content file naming conventions","Exclude extension-less or dot-suffixed oddities from glob patterns"],"tags":["astro","content-collections","glob-loader","file-extension"],"backgroundTag":"missing-file-extension","analyzedSha":"e294953aa8aadd98d5be92e60a03037b05dbdfd4","analyzedAt":"2026-08-18T18:48:03.901Z","contentChangedAt":"2026-08-18T18:48:03.901Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}