garrytan/gstack · error · Error
Usage: browse diff <url1> <url2>
Error message
Usage: browse diff <url1> <url2>
What it means
The `diff` meta-command requires exactly two URL arguments (`url1`, `url2`) so it can navigate to each in turn and compare their cleaned text via `Diff.diffLines` (lines 715-728). If either argument is missing the command throws this usage error before any network navigation.
Source
Thrown at browse/src/meta-commands.ts:717
results.push(`[${label}] ${result}`);
} catch (err: any) {
results.push(`[${label}] ERROR: ${err.message}`);
}
}
}
// Wait for network to settle after write commands before returning
if (lastWasWrite) {
await bm.getPage().waitForLoadState('networkidle', { timeout: 2000 }).catch(() => {});
}
return results.join('\n\n');
}
// ─── Diff ──────────────────────────────────────────
case 'diff': {
const [url1, url2] = args;
if (!url1 || !url2) throw new Error('Usage: browse diff <url1> <url2>');
const page = bm.getPage();
const normalizedUrl1 = await validateNavigationUrl(url1);
await page.goto(normalizedUrl1, { waitUntil: 'domcontentloaded', timeout: 15000 });
const text1 = await getCleanText(page);
const normalizedUrl2 = await validateNavigationUrl(url2);
await page.goto(normalizedUrl2, { waitUntil: 'domcontentloaded', timeout: 15000 });
const text2 = await getCleanText(page);
const changes = Diff.diffLines(text1, text2);
const output: string[] = [`--- ${url1}`, `+++ ${url2}`, ''];
for (const part of changes) {
const prefix = part.added ? '+' : part.removed ? '-' : ' ';
const lines = part.value.split('\n').filter(l => l.length > 0);
for (const line of lines) {
output.push(`${prefix} ${line}`);View on GitHub (pinned to 94993f7401)
Solutions
- Supply both URLs: `browse diff https://prod.example.com https://staging.example.com`.
- Quote URLs containing spaces, query params with `&`, or shell metacharacters.
- If you intended a single-page snapshot comparison, use `state save`/`state load` or external diff tooling instead.
Example fix
// before browse diff https://example.com // after browse diff https://example.com https://staging.example.com
Defensive patterns
Strategy: validation
Validate before calling
if (args.length < 2 || !args[0] || !args[1]) {
throw new Error('diff requires exactly two URL arguments');
}
if (!/^https?:\/\//.test(args[0]) || !/^https?:\/\//.test(args[1])) {
throw new Error('diff arguments must be absolute http(s) URLs');
} Type guard
const isUrl = (s: unknown): s is string => typeof s === 'string' && /^https?:\/\//.test(s);
Try / catch
try { await browse.diff(url1, url2); }
catch (err) {
if (/Usage: browse diff/.test(err.message)) {
// prompt the caller for the missing URL
}
} Prevention
- Type the diff wrapper as `(a: string, b: string) => ...` so the compiler enforces arity.
- Validate both URLs are absolute http(s) before dispatch.
When it happens
Trigger: Calling `browse diff https://a.example.com` (missing second URL) or `browse diff` with no args (line 716-717).
Common situations: Shell quoting that dropped one URL, an agent templating only one URL into the call, or comparing a URL against an empty baseline.
Related errors
- Usage: echo '[["goto","url"],["text"]]' | browse chain or
- Usage: state save|load <name>
- Usage: frame <selector|@ref|--name name|--url pattern|main>
- Usage: frame --name <name>
- Usage: frame --url <pattern>
AI-assisted analysis of garrytan/gstack@94993f7401 (2026-08-12).
Data as JSON: /api/errors/113d29e8d908a6b2.
Report an issue: GitHub.