Crosstalk-Solutions/project-nomad · warning · Error
File not found: ${filename}
Error message
File not found: ${filename} What it means
Thrown by DocsService.parseFile when the resolved file path passes the traversal guard but getFileStatsIfExists reports no fs.Stats — i.e. the .md file does not exist at that location (a non-existent slug, or the file was deleted/renamed). The '.md' extension is appended automatically if missing.
Source
Thrown at admin/app/services/docs_service.ts:82
async parseFile(_filename: string) {
try {
if (!_filename) {
throw new Error('Filename is required')
}
const filename = _filename.endsWith('.md') ? _filename : `${_filename}.md`
// Prevent path traversal — resolved path must stay within the docs directory
const basePath = path.resolve(this.docsPath)
const fullPath = path.resolve(path.join(this.docsPath, filename))
if (!fullPath.startsWith(basePath + path.sep)) {
throw new Error('Invalid document slug')
}
const fileExists = await getFileStatsIfExists(fullPath)
if (!fileExists) {
throw new Error(`File not found: ${filename}`)
}
const fileStream = await getFile(fullPath, 'stream')
if (!fileStream) {
throw new Error(`Failed to read file stream: ${filename}`)
}
const content = await streamToString(fileStream)
return this.parse(content)
} catch (error) {
throw new InternalServerErrorException(`Error parsing file: ${(error as Error).message}`)
}
}
private static readonly TITLE_OVERRIDES: Record<string, string> = {
'faq': 'FAQ',
'community-add-ons': 'Community Add-Ons',
}
View on GitHub (pinned to 0bd1c6f4f9)
Solutions
- Verify the file exists on disk: ls <docsPath>/<slug>.md with exact casing
- Check the docsPath configuration/mount in the running environment (container volume, env var)
- Fix or remove the stale link/alias pointing to the renamed doc
- Normalize doc filenames to lowercase and enforce it when creating docs
Example fix
// before
const doc = await docs.parseFile('Setup-Guide') // file is setup-guide.md
// after
const doc = await docs.parseFile('setup-guide') Defensive patterns
Strategy: validation
Validate before calling
import { getFileStatsIfExists } from '<storage util>'
const p = path.join(docsPath, `${slug}.md`)
if (!(await getFileStatsIfExists(p))) throw new NotFoundException(`Doc ${slug} not found`) Type guard
const docExists = async (slug: string): Promise<boolean> =>
Boolean(await getFileStatsIfExists(path.join(docsPath, `${slug}.md`))) Try / catch
try {
const doc = await docsService.parseFile(slug)
} catch (e) {
if ((e as Error).message.startsWith('File not found'))
throw new NotFoundException(`Doc '${slug}' not found`)
throw e
} Prevention
- Keep an index/manifest of doc slugs and validate links against it
- Normalize filenames to lowercase kebab-case at authoring time
- Test doc routes in CI on a case-sensitive filesystem
When it happens
Trigger: parseFile('nonexistent-doc') where docs/nonexistent-doc.md is absent; requesting a doc whose file was renamed or moved; case-sensitivity mismatch on case-sensitive filesystems; docs directory not mounted in the container.
Common situations: Stale frontend links after docs restructuring, docs volume not mounted in production, filename case mismatch (FAQ.md vs faq.md) between macOS dev and Linux prod, files not committed to the repo/deployment artifact.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- Failed to read file stream: ${filename}
- Storage drive not available: cannot write to ${STORAGE_BASE}
- Filename is required
- Invalid document slug
- Error parsing file: ${(error as Error).message}
AI-assisted analysis of Crosstalk-Solutions/project-nomad@0bd1c6f4f9 (2026-08-27).
Data as JSON: /api/errors/58e23302362dd914.
Report an issue: GitHub.