jackwener/OpenCLI · error · CommandExecutionError

ggbApplet not available after waiting. Make sure the GeoGebr

Error message

ggbApplet not available after waiting. Make sure the GeoGebra Geometry page is fully loaded.

What it means

ensureApplet() waits (with retries) for the ggbApplet global with an evalCommand function to appear on the GeoGebra Geometry page. If the poll completes without ready===true, it throws CommandExecutionError explaining that the applet never became available and that the page must be fully loaded. This indicates the page loaded but the applet JavaScript did not initialize in time.

Source

Thrown at clis/geogebra/utils.js:113

  let ready;
  try {
    ready = unwrapBridgeEnvelope(await page.evaluate(`
      (async () => {
        const deadline = Date.now() + ${APPLET_WAIT_MS};
        while (Date.now() < deadline) {
          if (typeof ggbApplet !== 'undefined' && typeof ggbApplet.evalCommand === 'function') {
            return true;
          }
          await new Promise(r => setTimeout(r, 500));
        }
        return false;
      })()
    `));
  } catch (err) {
    throw new CommandExecutionError(`Failed to detect GeoGebra applet: ${err?.message || err}`);
  }
  if (ready !== true) {
    throw new CommandExecutionError('ggbApplet not available after waiting. Make sure the GeoGebra Geometry page is fully loaded.');
  }
}

/**
 * Execute a GeoGebra command string via ggbApplet.evalCommandGetLabels.
 * evalCommandGetLabels both executes the command and returns the created
 * object label(s). We use it instead of evalCommand to avoid double-execution.
 * Returns { ok, label } where label is the resulting object label(s).
 */
export async function ggbEval(page, cmd) {
  let result;
  try {
    result = unwrapBridgeEnvelope(await page.evaluate(`
      (cmd => {
        if (typeof ggbApplet === 'undefined' || typeof ggbApplet.evalCommandGetLabels !== 'function') {
          return { ok: false, label: '', beforeCount: 0, afterCount: 0, error: 'ggbApplet is not ready' };
        }
        const collectNames = () => {

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Reload the page and retry — the applet often appears on a second load once assets are cached.
  2. Wait longer before the call or increase the tool's timeout so the applet has more time to boot.
  3. Disable extensions/ad-blockers that may block GeoGebra's script/CDN domains, or use a clean profile.
  4. Check that the page actually shows the Geometry app (not a consent/error page); solve the interstitial then retry.

Example fix

// before
await ensureApplet(page); // flaky on cold cache
// after
try { await ensureApplet(page); } catch (e) { await page.reload({ waitUntil: 'networkidle2' }); await ensureApplet(page); }
Defensive patterns

Strategy: retry

Validate before calling

// wait for applet before calling tools
await page.waitForFunction('typeof ggbApplet !== "undefined" && typeof ggbApplet.evalCommand === "function"', { timeout: 60000 });

Type guard

null

Try / catch

try { await ensureApplet(page); } catch (e) { if (String(e.message).includes('ggbApplet not available')) { await page.reload(); await ensureApplet(page); } else throw e; }

Prevention

When it happens

Trigger: Navigation finished but ggbApplet never defined: slow network stalling applet assets, GeoGebra serving a cookie/consent or error page instead of the applet, JavaScript disabled/blocked, or an outdated cached bundle failing to boot within the retry window.

Common situations: First-run cold cache on slow connections, regional CDN slowness, ad-blockers blocking geogebra script domains, bot protection interstitials in headless browsers, or heavily loaded shared CI machines timing out.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/fb4b70edc252543f. Report an issue: GitHub.