garrytan/gstack · error · Error
Invalid file URL: file://./ would list the current directory
Error message
Invalid file URL: file://./ would list the current directory. Use file://./<filename> to render a specific file.
What it means
Thrown by normalizeFileUrl when the input is `file://.` or `file://./` — the file scheme with `.` as the authority. These would make Chromium list the current working directory, which is a different product surface and a potential information leak, so the library demands an explicit filename.
Source
Thrown at browse/src/url-validation.ts:171
if (rest === '///' || rest === '////') {
throw new Error('Invalid file URL: file:/// has no path. Use file:///<absolute-path>.');
}
return pathPart + trailing;
}
// Everything else: must start with // (we accept file://... only)
if (!rest.startsWith('//')) {
throw new Error(`Invalid file URL: ${url}. Use file:///<absolute-path> or file://./<rel> or file://~/<rel>.`);
}
const afterDoubleSlash = rest.slice(2);
// Reject empty (file://) and trailing-slash-only (file://./ listing cwd).
if (afterDoubleSlash === '') {
throw new Error('Invalid file URL: file:// is empty. Use file:///<absolute-path>.');
}
if (afterDoubleSlash === '.' || afterDoubleSlash === './') {
throw new Error('Invalid file URL: file://./ would list the current directory. Use file://./<filename> to render a specific file.');
}
if (afterDoubleSlash === '~' || afterDoubleSlash === '~/') {
throw new Error('Invalid file URL: file://~/ would list the home directory. Use file://~/<filename> to render a specific file.');
}
// Home-relative: file://~/<rel>
if (afterDoubleSlash.startsWith('~/')) {
const rel = afterDoubleSlash.slice(2);
const absPath = path.join(os.homedir(), rel);
return pathToFileURL(absPath).href + trailing;
}
// cwd-relative with explicit ./ : file://./<rel>
if (afterDoubleSlash.startsWith('./')) {
const rel = afterDoubleSlash.slice(2);
const absPath = path.resolve(process.cwd(), rel);
return pathToFileURL(absPath).href + trailing;
}View on GitHub (pinned to 94993f7401)
Solutions
- Always include the filename: `file://./index.html`.
- When constructing from a directory + filename, default the filename to 'index.html' if empty.
- Validate that the joined path has a non-empty basename before building the URL.
Example fix
// before
await goto(`file://./${name}/`); // name empty → file://./
// after
const file = name || 'index.html';
await goto(`file://./${file}`); Defensive patterns
Strategy: validation
Validate before calling
function requireFileFilename(u: string): void {
const lower = u.toLowerCase();
if (lower === 'file://.' || lower === 'file://./') {
throw new Error('file://./ requires a filename');
}
} Type guard
const hasCwdRelativeFilename = (u: string): boolean => {
const m = /^file:\/\/(\.\/)?(.+)$/i.exec(u);
return !!m && m[2].length > 0 && m[2] !== '/';
}; Try / catch
try {
await goto(url);
} catch (e: any) {
if (/file:\/\.\/ would list/.test(e.message)) {
await goto(`file://./index.html`);
} else throw e;
} Prevention
- Always join a filename onto the `file://./` prefix.
- Default to index.html when the filename is missing.
- Strip trailing slashes from user input before constructing the URL.
- Validate basename non-empty at the caller boundary.
When it happens
Trigger: Calling goto with `file://./` (trailing slash, no filename); building a URL as `file://${rel}/` where rel is `.`; auto-completing a path with a trailing slash.
Common situations: A user trying to 'open the current folder'; a fixture loader that joins `./` + '' when no fixture name is provided; IDE tab-completion inserting a trailing slash.
Related errors
- Invalid file URL: file:/// has no path. Use file:///<absolut
- Invalid file URL: file://~/ would list the home directory. U
- Invalid file URL: ${url}. Use file:///<absolute-path> or fil
- Invalid file URL: file:// is empty. Use file:///<absolute-pa
- Unsupported file URL host: ${segment}. Use file:///<absolute
AI-assisted analysis of garrytan/gstack@94993f7401 (2026-08-12).
Data as JSON: /api/errors/226b711cbe5dc4c3.
Report an issue: GitHub.