unclecode/crawl4ai · warning · RuntimeError
Failed to evaluate wait condition: {str(e)}
Error message
Failed to evaluate wait condition: {str(e)} What it means
A 400 Bad Request raised during stream-crawl setup when the submitted configuration fails trust validation: crawler_config is loaded via `CrawlerRunConfig.load(..., provenance=Provenance.UNTRUSTED)` and hook configs are validated, so any field or hook the server does not allow for untrusted clients raises UntrustedConfigError or HookValidationError. The crawler instance is released and the rejection message is echoed back.
Source
Thrown at crawl4ai/async_crawler_strategy.py:340
return true;
}}
if (Date.now() - startTime > {timeout}) {{
return false; // Return false instead of throwing
}}
await new Promise(resolve => setTimeout(resolve, 100));
}}
}} catch (error) {{
throw new Error(`Error evaluating condition: ${{error.message}}`);
}}
}}
"""
try:
result = await self.adapter.evaluate(page, wrapper_js)
return result
except Exception as e:
if "Error evaluating condition" in str(e):
raise RuntimeError(f"Failed to evaluate wait condition: {str(e)}")
# For timeout or other cases, just return False
return False
async def process_iframes(self, page):
"""
Process iframes on a page. This function will extract the content of each iframe and replace it with a div containing the extracted content.
Args:
page: Playwright page object
Returns:
Playwright page object
"""
# Find all iframes
iframes = await page.query_selector_all("iframe")
for i, iframe in enumerate(iframes):
try:View on GitHub (pinned to 7e80152142)
Solutions
- Read the detail text — it names the exact rejected field/hook; remove or correct that key
- Send only allowlisted crawler_config fields for untrusted clients; run admin/local mode if the option is genuinely needed
- Validate hooks_config against the documented hook schema (event names, signatures) before submitting
Example fix
# before
payload = {"urls": [u], "crawler_config": {"browser_agent": "...", "verbose": True, "magic": True}}
# after
payload = {"urls": [u], "crawler_config": {"browser_agent": "..."}} # only allowlisted keys Defensive patterns
Strategy: validation
Validate before calling
ALLOWED_CRAWLER_KEYS = {"word_count_threshold", "only_text", "screenshot", "pdf"}
def sanitize(cfg):
bad = set(cfg) - ALLOWED_CRAWLER_KEYS
if bad:
raise ValueError(f"untrusted config rejects: {bad}")
return cfg Try / catch
try:
crawler, gen, hooks = await setup_stream(urls, browser_cfg, crawler_cfg, hooks_cfg)
except HTTPException as e:
if e.status_code == 400:
report_config_rejection(e.detail) # name the rejected key to the user
raise Prevention
- Keep a client-side allowlist mirroring the server's untrusted config allowlist
- Validate hooks_config schema (event names, signatures) before submitting
- Log the 400 detail verbatim; it names the offending field
When it happens
Trigger: POSTing to the stream endpoint with a crawler_config key that the server's untrusted-allowlist rejects (e.g. arbitrary callable, internal-only option) or a hooks_config that fails HookValidationError (bad event name, invalid hook spec).
Common situations: Porting a local script's full config object to the HTTP API without pruning server-side-only fields; upgrading the server so a previously accepted option moves off the untrusted allowlist; sending hooks with wrong schema.
Related errors
- Rejected request: {e}
- Container not found: ${config.container_selector}
- HTTP request failed: {str(e)}
- Hook '{hook_name}' must be a callable function, got {type(ho
- Cannot extract source code for hook '{hook_name}'. Make sure
AI-assisted analysis of unclecode/crawl4ai@7e80152142 (2026-08-14).
Data as JSON: /api/errors/6f5e99b41b8f0f66.
Report an issue: GitHub.