garrytan/gstack · error · Error
Invalid file URL: file:// is empty. Use file:///<absolute-pa
Error message
Invalid file URL: file:// is empty. Use file:///<absolute-path>.
What it means
Thrown by normalizeFileUrl when the input is exactly `file://` — the scheme plus authority separator and nothing else. With no path and no host the URL is empty and would resolve to a directory listing of the cwd, which the library refuses so the caller must specify a concrete file.
Source
Thrown at browse/src/url-validation.ts:168
// file:/// or longer → standard absolute; pass through unchanged (caller validates path).
if (rest.startsWith('///')) {
// Reject bare root-only (file:/// with nothing after)
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);View on GitHub (pinned to 94993f7401)
Solutions
- Supply a concrete file: `file:///tmp/index.html`.
- Use pathToFileURL on an absolute path so the slash count and path are always present.
- Reject empty paths at the caller boundary before constructing the URL.
Example fix
// before
await goto(`file://${maybePath}`); // maybePath === ''
// after
if (!maybePath) throw new Error('path required');
await goto(pathToFileURL(path.resolve(maybePath)).href); Defensive patterns
Strategy: validation
Validate before calling
function requireNonEmptyFileUrl(u: string): void {
if (u.toLowerCase() === 'file://') {
throw new Error('Invalid file URL: file:// is empty. Use file:///<absolute-path>.');
}
} Type guard
const isNonEmptyFileUrl = (u: string): boolean =>
u.toLowerCase() !== 'file://' && u.toLowerCase().startsWith('file:'); Try / catch
try {
await goto(url);
} catch (e: any) {
if (/file:\/\/ is empty/.test(e.message)) {
await goto(pathToFileURL(path.resolve('index.html')).href);
} else throw e;
} Prevention
- Reject empty path input before constructing the URL.
- Build file URLs from concrete paths with pathToFileURL.
- Treat an empty user input as a caller-side error, not a default-to-cwd.
- Add a unit test for the empty-string case in your URL builder.
When it happens
Trigger: Calling goto with the literal string `file://`; building a URL by concatenating `file://` + '' + nothing else; trimming a path down to nothing before joining.
Common situations: A template like `file://${host}` where host is empty; a CLI flag that takes an optional file path and the user supplied none; a copy-paste that dropped the path segment.
Related errors
- Invalid file URL: file:/// has no path. Use file:///<absolut
- Invalid file URL: ${url}. Use file:///<absolute-path> or fil
- Invalid file URL: file://./ would list the current directory
- Invalid file URL: file://~/ would list the home directory. U
- Unsupported file URL host: ${segment}. Use file:///<absolute
AI-assisted analysis of garrytan/gstack@94993f7401 (2026-08-12).
Data as JSON: /api/errors/d3687c15a58126dc.
Report an issue: GitHub.