unclecode/crawl4ai · warning · ValueError
Invalid CSS selector: '{css_selector}'
Error message
Invalid CSS selector: '{css_selector}' What it means
QuotaExceeded is raised by write_artifact when adding this artifact would push the total on-disk size of the artifact store past ARTIFACT_QUOTA_BYTES (env CRAWL4AI_ARTIFACT_QUOTA_BYTES, default 2 GiB). Unlike the per-item cap, this is a shared budget across all stored artifacts; expired artifacts are reaped by a janitor, so the quota is recoverable.
Source
Thrown at crawl4ai/async_crawler_strategy.py:269
"""
wait_for = wait_for.strip()
if wait_for.startswith("js:"):
# Explicitly specified JavaScript
js_code = wait_for[3:].strip()
return await self.csp_compliant_wait(page, js_code, timeout)
elif wait_for.startswith("css:"):
# Explicitly specified CSS selector
css_selector = wait_for[4:].strip()
try:
await page.wait_for_selector(css_selector, timeout=timeout)
except Error as e:
if "Timeout" in str(e):
raise TimeoutError(
f"Timeout after {timeout}ms waiting for selector '{css_selector}'"
)
else:
raise ValueError(f"Invalid CSS selector: '{css_selector}'")
else:
# Auto-detect based on content
if wait_for.startswith("()") or wait_for.startswith("function"):
# It's likely a JavaScript function
return await self.csp_compliant_wait(page, wait_for, timeout)
else:
# Assume it's a CSS selector first
try:
await page.wait_for_selector(wait_for, timeout=timeout)
except Error as e:
if "Timeout" in str(e):
raise TimeoutError(
f"Timeout after {timeout}ms waiting for selector '{wait_for}'"
)
else:
# If it's not a timeout error, it might be an invalid selector
# Let's try to evaluate it as a JavaScript function as a fallback
try:View on GitHub (pinned to 7e80152142)
Solutions
- Trigger or wait for the janitor/TTL sweep (expired artifacts are unlinked, freeing quota) and retry
- Raise CRAWL4AI_ARTIFACT_QUOTA_BYTES if the volume is legitimate and disk allows
- Lower CRAWL4AI_TTL (CRAWL4AI_ARTIFACT_TTL_SECONDS) so artifacts age out faster under sustained load
Example fix
# server: free quota via janitor endpoint/call, or raise budget # docker-compose.yml environment: CRAWL4AI_ARTIFACT_QUOTA_BYTES: "5368709120" # 5 GiB CRAWL4AI_ARTIFACT_TTL_SECONDS: "1800"
Defensive patterns
Strategy: retry
Try / catch
from artifacts import write_artifact, QuotaExceeded
try:
meta = write_artifact(kind, data)
except QuotaExceeded:
janitor() # reap expired artifacts to free budget
meta = write_artifact(kind, data) # one bounded retry Prevention
- Run/schedule the janitor regularly under sustained artifact-producing load
- Monitor store size against CRAWL4AI_ARTIFACT_QUOTA_BYTES and alert before it fills
- Set TTL short enough that artifact production rate x TTL stays under quota
When it happens
Trigger: Storing an artifact when _dir_size() + len(data) > 2 GiB (or configured quota) — e.g. sustained crawl runs generating screenshots/PDFs until the store fills, with the TTL (default 1 h) not yet expiring old entries.
Common situations: High-throughput batch crawls producing many media artifacts; a low quota set for a small disk; janitor not running often enough so expired artifacts still count toward the measured size.
Related errors
- Timeout after {timeout}ms waiting for selector '{css_selecto
- Artifact storage quota exceeded
- Timeout after {timeout}ms waiting for selector '{wait_for}'
- Invalid wait_for parameter: '{wait_for}'. It should be eithe
- Invalid config
AI-assisted analysis of unclecode/crawl4ai@7e80152142 (2026-08-14).
Data as JSON: /api/errors/830bc2ac9de95769.
Report an issue: GitHub.