garrytan/gstack · error · Error
load-html: --from-file html too large (> ${MAX_BYTES} bytes)
Error message
load-html: --from-file html too large (> ${MAX_BYTES} bytes). Raise with GSTACK_BROWSE_MAX_HTML_BYTES=<N>. What it means
Size cap at write-commands.ts:233-236. The html string in the --from-file payload is measured in UTF-8 bytes; if it exceeds MAX_BYTES the load is refused. The default cap is 50 MiB, overridable by the GSTACK_BROWSE_MAX_HTML_BYTES environment variable.
Source
Thrown at browse/src/write-commands.ts:235
fromFilePayload = { html: json.html, waitUntil: json.waitUntil };
} else if (args[i] === '--wait-until') {
const val = args[++i];
if (val !== 'load' && val !== 'domcontentloaded' && val !== 'networkidle') {
throw new Error(`Invalid --wait-until '${val}'. Must be one of: load, domcontentloaded, networkidle.`);
}
waitUntil = val;
} else if (args[i].startsWith('--')) {
throw new Error(`Unknown flag: ${args[i]}`);
} else if (!filePath) {
filePath = args[i];
}
}
// Inline HTML path: validate size + magic byte, then setContent directly.
if (fromFilePayload) {
const MAX_BYTES = parseInt(process.env.GSTACK_BROWSE_MAX_HTML_BYTES || '', 10) || (50 * 1024 * 1024);
if (Buffer.byteLength(fromFilePayload.html, 'utf8') > MAX_BYTES) {
throw new Error(
`load-html: --from-file html too large (> ${MAX_BYTES} bytes). ` +
'Raise with GSTACK_BROWSE_MAX_HTML_BYTES=<N>.'
);
}
const peek = fromFilePayload.html.trimStart();
if (!/^<[a-zA-Z!?]/.test(peek)) {
throw new Error('load-html: --from-file html does not start with a valid markup opener');
}
const finalWaitUntil = fromFilePayload.waitUntil ?? waitUntil;
await session.setTabContent(fromFilePayload.html, { waitUntil: finalWaitUntil });
return `Loaded HTML: (inline from --from-file, ${fromFilePayload.html.length} chars)`;
}
if (!filePath) throw new Error('Usage: browse load-html <file> [--wait-until load|domcontentloaded|networkidle] [--tab-id <N>] | load-html --from-file <payload.json> [--tab-id <N>]');
// Extension allowlist
const ALLOWED_EXT = ['.html', '.htm', '.xhtml', '.svg'];
const ext = path.extname(filePath).toLowerCase();View on GitHub (pinned to 94993f7401)
Solutions
- Reduce the HTML: externalize large assets (images, scripts) to files or URLs
- Raise the cap by setting GSTACK_BROWSE_MAX_HTML_BYTES=<bytes> before starting the browse server
- Load the page from a served http://localhost URL instead of inlining
Example fix
// before — default 50 MiB cap exceeded // after — raise the cap when launching the browse server GSTACK_BROWSE_MAX_HTML_BYTES=$((100*1024*1024)) ./browse-server
Defensive patterns
Strategy: validation
Validate before calling
function withinHtmlCap(html: string): boolean {
const cap = parseInt(process.env.GSTACK_BROWSE_MAX_HTML_BYTES || '', 10) || (50*1024*1024)
return Buffer.byteLength(html, 'utf8') <= cap
} Prevention
- Externalize large embedded assets (base64 images, inlined JS/CSS)
- Raise GSTACK_BROWSE_MAX_HTML_BYTES only when genuinely needed
- Prefer served http://localhost content for very large pages
When it happens
Trigger: A payload whose html field is larger than the cap — typically due to large embedded base64 images, inlined CSS/JS, or a generated report.
Common situations: HTML with many data: URIs; concatenated component snapshots; a generation pipeline that inlines all assets.
Related errors
- Cannot use load-html inside a frame. Run 'frame main' first.
- load-html: --from-file requires a path
- load-html: --from-file ${payloadPath} must be under ${SAFE_D
- load-html: --from-file JSON parse failed: ${e.message}
- load-html: --from-file JSON must have a "html" string field
AI-assisted analysis of garrytan/gstack@94993f7401 (2026-08-12).
Data as JSON: /api/errors/996c4a264ff1cdd2.
Report an issue: GitHub.