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

  1. Reduce the HTML: externalize large assets (images, scripts) to files or URLs
  2. Raise the cap by setting GSTACK_BROWSE_MAX_HTML_BYTES=<bytes> before starting the browse server
  3. 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

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


AI-assisted analysis of garrytan/gstack@94993f7401 (2026-08-12). Data as JSON: /api/errors/996c4a264ff1cdd2. Report an issue: GitHub.