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

  1. Verify the file exists on disk: ls <docsPath>/<slug>.md with exact casing
  2. Check the docsPath configuration/mount in the running environment (container volume, env var)
  3. Fix or remove the stale link/alias pointing to the renamed doc
  4. 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

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


AI-assisted analysis of Crosstalk-Solutions/project-nomad@0bd1c6f4f9 (2026-08-27). Data as JSON: /api/errors/58e23302362dd914. Report an issue: GitHub.