garrytan/gstack · error · Error
Cannot resolve path: ${filePath}
Error message
Cannot resolve path: ${filePath} What it means
Thrown by validateTempPath when realpathSync fails with an errno other than ENOENT (e.g., EACCES). The file may exist but the browse process cannot resolve its real path due to permissions or a broken symlink in TEMP_DIR, so the raw 'Cannot resolve path' error is surfaced.
Source
Thrown at browse/src/path-security.ts:111
}
}
const isSafe = SAFE_DIRECTORIES.some(dir => isPathWithin(realPath, dir));
if (!isSafe) {
throw new Error(`Path must be within: ${SAFE_DIRECTORIES.join(', ')}`);
}
}
/** Validate a file path for remote serving (GET /file). TEMP_DIR only, not cwd. */
export function validateTempPath(filePath: string): void {
const resolved = path.resolve(filePath);
let realPath: string;
try {
realPath = fs.realpathSync(resolved);
} catch (err: any) {
if (err.code === 'ENOENT') {
throw new Error('File not found');
}
throw new Error(`Cannot resolve path: ${filePath}`);
}
const isSafe = TEMP_ONLY.some(dir => isPathWithin(realPath, dir));
if (!isSafe) {
throw new Error(`Path must be within: ${TEMP_ONLY.join(', ')} (remote file serving is restricted to temp directory)`);
}
}
/** Escape special regex metacharacters in a user-supplied string to prevent ReDoS. */
export function escapeRegExp(s: string): string {
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
View on GitHub (pinned to 94993f7401)
Solutions
- Check permissions on the file and every component of the path: `namei -l <path>`
- Remove broken symlinks in TEMP_DIR: `find <TEMP_DIR> -xtype l -delete`
- Regenerate the file so it is owned by the current browse process
- If the file is from another user, copy it into a fresh temp path owned by this process
Defensive patterns
Strategy: try-catch
Validate before calling
import * as fs from 'fs';
function isResolvableTempPath(p: string): boolean {
try { fs.realpathSync(p); return true; }
catch (e: any) { return e.code !== 'ENOENT' ? false : false; }
}
// Distinguish ENOENT (caught as 'File not found') from other errors
function tempPathStatus(p: string): 'ok' | 'missing' | 'unresolvable' {
try { fs.realpathSync(p); return 'ok'; }
catch (e: any) {
if (e.code === 'ENOENT') return 'missing';
return 'unresolvable';
}
} Type guard
function isReadableTempFile(p: string): boolean {
try { fs.realpathSync(p); fs.accessSync(p, fs.constants.R_OK); return true; } catch { return false; }
} Try / catch
try {
return serveTempFile(filePath);
} catch (e: any) {
if (/Cannot resolve path/.test(e.message)) {
return { status: 500, body: 'Temp file exists but cannot be resolved (permissions or broken symlink)' };
}
throw e;
} Prevention
- Run writer and reader as the same user so permissions match
- Clean broken symlinks in TEMP_DIR before serving
- Regenerate artifacts in the current process rather than reusing files from another user
- Use fs.accessSync(R_OK) to preflight before serving
When it happens
Trigger: Requesting a temp file whose path cannot be resolved: permission denied on a path component, a broken symlink in TEMP_DIR, or an I/O error reading the directory.
Common situations: Permission mismatch between the browse process and the file owner (file written by a different user); broken symlink leftover in TEMP_DIR; filesystem corruption or transient I/O error.
Related errors
- Cannot resolve real path: ${filePath} (${err.code})
- File not found
- Path must be within: ${TEMP_ONLY.join(', ')} (remote file se
- Cannot resolve real path: ${screenshotPath} (${err.code})
- Cannot resolve real path: ${heatmapPath} (${err.code})
AI-assisted analysis of garrytan/gstack@94993f7401 (2026-08-12).
Data as JSON: /api/errors/67355f3ff7877cde.
Report an issue: GitHub.