jackwener/OpenCLI · warning · Error

Working tree not clean: ${status}

Error message

Working tree not clean:
${status}

What it means

This EMPTY_RESULT error is thrown by extractEventRowsPayload when the Huodongxing events page contained zero event cards at all — the code path after the MALFORMED_RESULT branch. It means extraction found no candidate elements whatsoever, so the page was either genuinely empty or its DOM layout changed so much that no cards were recognized. Unlike MALFORMED_RESULT, no card-like markup was seen.

Source

Thrown at autoresearch/engine.ts:94

  constructor(config: AutoResearchConfig, logPath: string, callbacks: EngineCallbacks) {
    this.config = config;
    this.logger = new Logger(logPath);
    this.callbacks = callbacks;
  }

  private log(msg: string): void {
    this.callbacks.onStatus?.(msg);
  }

  /** Phase 0: Precondition checks */
  private checkPreconditions(): void {
    // Git repo exists
    try { execStrict('git rev-parse --git-dir'); }
    catch { throw new Error('Not a git repository'); }

    // Clean working tree
    const status = exec('git status --porcelain');
    if (status) throw new Error(`Working tree not clean:\n${status}`);

    // No stale locks
    if (existsSync(join(ROOT, '.git', 'index.lock'))) {
      throw new Error('Stale .git/index.lock found — remove it first');
    }

    // Not detached HEAD
    try { execStrict('git symbolic-ref HEAD'); }
    catch { throw new Error('Detached HEAD — checkout a branch first'); }
  }

  /** Phase 5: Run verify command and extract metric */
  private runVerify(): number | null {
    this.log('  verify...');
    const output = exec(this.config.verify, { timeout: 300_000 });
    return extractMetric(output);
  }

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Retry after a short wait — a temporary busy/interstitial page can look empty; use the same browser session/cookies.
  2. Dump the fetched HTML and check whether real event cards exist under different selectors; update the card selector in extractEventRowsPayload if the DOM changed.
  3. Verify the target URL and pagination parameters actually point at a populated events listing.
  4. If the listing is legitimately empty, treat EMPTY_RESULT as an expected business outcome rather than a fault.

Example fix

// before
const rows = extractFromPayload(html);
// after
if (!rows.length) {
  const html = await page.content();
  require('fs').writeFileSync('debug-events.html', html); // inspect and update selectors
}
Defensive patterns

Strategy: retry

Validate before calling

const html = await page.content();
if (!html.includes('event') && html.length < 2000) {
  console.warn('Events page looks empty/interstitial — likely busy page; retry before extraction');
}

Type guard

function hasEventRows(payload: unknown): payload is { rows: unknown[] } {
  return typeof payload === 'object' && payload !== null &&
    Array.isArray((payload as any).rows) && (payload as any).rows.length > 0;
}

Try / catch

try {
  const res = await extractEventRows();
} catch (err) {
  if (err.code === 'EMPTY_RESULT') {
    await sleep(RETRY_DELAY_MS);
    return retryExtract(); // busy pages often look empty on first hit
  }
  throw err;
}

Prevention

When it happens

Trigger: extractEventRows runs against a fetched Huodongxing events page whose card selector matches 0 elements (cards.length === 0) and no earlier guard (busy page / malformed cards) fired.

Common situations: The events listing genuinely has no upcoming events; the request landed on an empty shell page because a bot wall blocked the content; the site moved the events list to a new container so the scraper's selector no longer matches anything; network fetch silently returned a near-empty page.

Related errors


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