GopeedLab/gopeed · error

invalid waitUntil: %s

Error message

invalid waitUntil: %s

What it means

normalizeWaitUntil validates the waitUntil option of page.goto. Unlike Playwright/Puppeteer, this webview layer supports only 'load' (the default when empty) and 'domcontentloaded', compared case-insensitively after trimming. Any other string — notably 'networkidle', 'networkidle0', 'networkidle2', 'commit' — is rejected.

Source

Thrown at pkg/download/engine/webview/runtime.go:504

		return GotoOptions{}, err
	}
	return GotoOptions{
		TimeoutMS: parseInt64(raw["timeoutMs"]),
		WaitUntil: waitUntil,
	}, nil
}

func normalizeWaitUntil(raw string) (string, error) {
	if raw == "" {
		return "load", nil
	}
	switch strings.ToLower(strings.TrimSpace(raw)) {
	case "load":
		return "load", nil
	case "domcontentloaded":
		return "domcontentloaded", nil
	default:
		return "", fmt.Errorf("invalid waitUntil: %s", raw)
	}
}

func parseClickOptions(raw map[string]any) ClickOptions {
	return ClickOptions{DelayMS: parseInt64(raw["delay"])}
}

func parseTypeOptions(raw map[string]any) TypeOptions {
	return TypeOptions{DelayMS: parseInt64(raw["delay"])}
}

func parseWaitOptions(raw map[string]any) WaitOptions {
	return WaitOptions{
		TimeoutMS:      parseInt64(raw["timeoutMs"]),
		PollIntervalMS: parseInt64(raw["pollIntervalMs"]),
	}
}

View on GitHub (pinned to 7b7327ffb3)

Solutions

  1. Use 'domcontentloaded' plus waitForSelector/waitForFunction for data-driven pages instead of networkidle
  2. Omit waitUntil entirely when 'load' semantics are fine
  3. Lower-case and trim the value if it comes from user config

Example fix

// before
await page.goto(url, { waitUntil: 'networkidle' }); // -> invalid waitUntil: networkidle
// after
await page.goto(url, { waitUntil: 'domcontentloaded' });
await page.waitForSelector('.result-item');
Defensive patterns

Strategy: validation

Validate before calling

// JS: whitelist before goto
const WAIT_UNTIL = new Set(['load', 'domcontentloaded']);
function normWaitUntil(v) {
  const s = String(v || '').trim().toLowerCase();
  return WAIT_UNTIL.has(s) ? s : 'load';
}
await page.goto(url, { waitUntil: normWaitUntil(cfg.waitUntil) });

Prevention

When it happens

Trigger: page.goto(url, {waitUntil: 'networkidle'}) copied from a Playwright script; passing 'networkidle0' from Puppeteer habits; a typo like 'load ' (handled) vs 'loaded' (rejected).

Common situations: Porting browser-automation code from Puppeteer/Playwright to a gopeed extension; waiting for XHR-driven SPAs where authors reach for networkidle by reflex.

Related errors


AI-assisted analysis of GopeedLab/gopeed@7b7327ffb3 (2026-08-16). Data as JSON: /api/errors/c7aaa8df15a31016. Report an issue: GitHub.