Crosstalk-Solutions/project-nomad · error · Error
Failed to read file stream: ${filename}
Error message
Failed to read file stream: ${filename} What it means
Thrown when the docs file exists (stats found) but getFile(fullPath, 'stream') returns a falsy stream — the storage layer could not open the file for reading despite it being stat-able. This indicates an I/O or permission-level failure rather than a missing file.
Source
Thrown at admin/app/services/docs_service.ts:87
}
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',
}
private prettify(filename: string) {
const slug = filename.replace(/\.md$/, '')
if (DocsService.TITLE_OVERRIDES[slug]) {
return DocsService.TITLE_OVERRIDES[slug]
}View on GitHub (pinned to 0bd1c6f4f9)
Solutions
- Check process read permissions: run as the app user, `head <docsPath>/<slug>.md`
- Fix ownership/mode: chown/chmod the docs directory to the app's uid/gid
- If getFile wraps a storage SDK, inspect its logs for the underlying open failure
- Handle deletion races by re-checking existence and returning a not-found response
Example fix
// before
// docs dir owned by root; app user cannot open files
const doc = await docs.parseFile('faq')
// after (ops fix)
// chown -R appuser:appuser /path/to/docs && chmod -R u+rwX /path/to/docs
const doc = await docs.parseFile('faq') Defensive patterns
Strategy: try-catch
Validate before calling
import { access } from 'node:fs/promises'
await access(path.join(docsPath, `${slug}.md`), fsConstants.R_OK)
// readable — stream failure is then unlikely Try / catch
try {
const doc = await docsService.parseFile(slug)
} catch (e) {
if ((e as Error).message.includes('Failed to read file stream')) {
logger.error('Permissions/I-O issue on docs dir', { slug })
throw new ServiceUnavailableException('Docs storage unavailable')
}
throw e
} Prevention
- Run the app as the user that owns the docs directory
- Set explicit u+rwX on docs in container entrypoints or Dockerfile
- Monitor disk space and read-only mount conditions on the docs volume
When it happens
Trigger: File exists but is not readable by the process (permissions/ownership), the underlying storage backend (e.g. abstracted getFile) fails to open the path, or a race where the file is deleted between the stats check and the open call.
Common situations: Docs directory owned by root while the app runs as non-root, read-only filesystem mounts, NFS/object-storage-backed getFile implementations erroring, files with restrictive modes created by another user.
Related errors
- Storage drive not available: cannot write to ${STORAGE_BASE}
- File not found: ${filename}
- 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/9b9e8c75cdfaa2e1.
Report an issue: GitHub.