garrytan/gstack · warning · Error
load-html: --from-file requires a path
Error message
load-html: --from-file requires a path
What it means
Argument guard at write-commands.ts:192. The --from-file flag consumes the next token via args[++i]; if that token is undefined (--from-file is the last arg) or empty, payloadPath is falsy and the command refuses to proceed rather than reading an unintended path.
Source
Thrown at browse/src/write-commands.ts:192
await page.reload({ waitUntil: 'domcontentloaded', timeout: 15000 });
return `Reloaded ${page.url()}`;
}
case 'load-html': {
if (inFrame) throw new Error('Cannot use load-html inside a frame. Run \'frame main\' first.');
// --from-file <path.json>: read inline HTML from a JSON payload. Used by
// make-pdf to dodge Windows argv size limits on large rendered HTML.
// The JSON shape is { html: string, waitUntil?: "load"|"domcontentloaded"|"networkidle" }.
// The safe-dirs + magic-byte + size-cap checks below still apply to the
// INLINE HTML content, not to the payload file path itself.
let fromFilePayload: { html: string; waitUntil?: SetContentWaitUntil } | null = null;
let filePath: string | undefined;
let waitUntil: SetContentWaitUntil = 'domcontentloaded';
for (let i = 0; i < args.length; i++) {
if (args[i] === '--from-file') {
const payloadPath = args[++i];
if (!payloadPath) throw new Error('load-html: --from-file requires a path');
// Parity with the sibling `load-html <file>` path below (line 249):
// that branch runs every `file://` target through validateReadPath
// so the safe-dirs policy can't be side-stepped. Same policy must
// apply here — otherwise --from-file becomes a read-anywhere escape
// hatch for any caller that can pick the payload path (e.g., an
// MCP caller issuing load-html with an attacker-influenced path).
try {
validateReadPath(path.resolve(payloadPath));
} catch {
throw new Error(
`load-html: --from-file ${payloadPath} must be under ${SAFE_DIRECTORIES.join(' or ')} (security policy). Copy the payload into the project tree or /tmp first.`
);
}
const raw = fs.readFileSync(payloadPath, 'utf8');
let json: any;
try { json = JSON.parse(raw); }
catch (e: any) { throw new Error(`load-html: --from-file JSON parse failed: ${e.message}`); }
if (typeof json.html !== 'string') {View on GitHub (pinned to 94993f7401)
Solutions
- Supply the payload path immediately after the flag: load-html --from-file ./payload.json
- Validate the args array length in automation before invoking
- Ensure the path token is non-empty and present
Example fix
// before
await handleWriteCommand('load-html', ['--from-file'], session, bm)
// after
await handleWriteCommand('load-html', ['--from-file', './payload.json'], session, bm) Defensive patterns
Strategy: validation
Validate before calling
function requireFromFilePath(args: string[], i: number): string {
const p = args[i + 1]
if (!p) throw new Error('--from-file requires a path')
return p
} Type guard
function hasFromFileTarget(args: string[]): boolean {
const i = args.indexOf('--from-file')
return i >= 0 && typeof args[i + 1] === 'string' && args[i + 1].length > 0
} Prevention
- Always pair --from-file with an immediate path token
- Validate args length in automation before invoking
When it happens
Trigger: load-html --from-file with no following token (last argument), or followed by an empty string; e.g. 'load-html --from-file' alone.
Common situations: Truncated command, a templating bug that drops the path, or quoting that yields an empty value.
Related errors
- Unknown flag: ${args[i]}
- Usage: browse goto <url>
- Invalid --wait-until '${val}'. Must be one of: load, domcont
- Cannot use load-html inside a frame. Run 'frame main' first.
- load-html: --from-file ${payloadPath} must be under ${SAFE_D
AI-assisted analysis of garrytan/gstack@94993f7401 (2026-08-12).
Data as JSON: /api/errors/84d437c87f1e3600.
Report an issue: GitHub.