unclecode/crawl4ai · error · ValueError
Invalid hook type: {hook_type}
Error message
Invalid hook type: {hook_type} What it means
A 500 raised by the stream-crawl setup path when a generic Exception (not config rejection, not a deliberate HTTPException) occurs while acquiring a crawler or starting `arun_many` — before the StreamingResponse begins. The crawler is released and the raw `str(e)` is returned as the detail, because once streaming starts this handler can no longer run.
Source
Thrown at crawl4ai/async_crawler_strategy.py:188
- on_execution_started: Called when the execution starts.
- before_goto: Called before a goto operation.
- after_goto: Called after a goto operation.
- before_return_html: Called before returning HTML content.
- before_retrieve_html: Called before retrieving HTML content.
All hooks except on_browser_created accepts a context and a page as arguments and **kwargs. However, on_browser_created accepts a browser and a context as arguments and **kwargs.
Args:
hook_type (str): The type of the hook.
hook (Callable): The hook function to set.
Returns:
None
"""
if hook_type in self.hooks:
self.hooks[hook_type] = hook
else:
raise ValueError(f"Invalid hook type: {hook_type}")
async def execute_hook(self, hook_type: str, *args, **kwargs):
"""
Execute a hook function for a specific hook type.
Args:
hook_type (str): The type of the hook.
*args: Variable length positional arguments.
**kwargs: Keyword arguments.
Returns:
The return value of the hook function, if any.
"""
hook = self.hooks.get(hook_type)
if hook:
if asyncio.iscoroutinefunction(hook):
return await hook(*args, **kwargs)
else:View on GitHub (pinned to 7e80152142)
Solutions
- Read `detail` (raw exception message) and the server log line 'Stream crawl error:' with its traceback for the root cause
- If it is a browser/Playwright startup failure, verify the docker image and run the browser health check; restart the container if the pool is wedged
- Retry with backoff — transient browser launch races commonly self-heal
- Simplify the payload (no custom dispatcher/hooks) to isolate whether config-driven setup code is the trigger
Defensive patterns
Strategy: retry
Validate before calling
# preflight: confirm the service is healthy before streaming
async def preflight(client):
r = await client.get("/health")
r.raise_for_status()
return True Try / catch
for attempt in range(3):
try:
crawler, gen, hooks = await setup_stream(...)
break
except HTTPException as e:
if e.status_code == 500 and attempt < 2:
await asyncio.sleep(2 ** attempt) # browser startup races often heal
continue
raise Prevention
- Check /health before long streaming sessions
- Watch server logs for 'Stream crawl error:' to catch recurring setup faults early
- Keep stream payloads minimal (no exotic dispatcher config) to shrink the setup error surface
When it happens
Trigger: POSTing to the stream endpoint when browser acquisition fails (browser pool crash, Playwright launch error) or `crawler.arun_many(...)` throws during dispatcher setup. Note this covers setup only; errors during an already-started stream surface differently.
Common situations: Chromium missing or crashed in the container, browser pool exhausted/broken after an earlier OOM, dispatcher misconfiguration in the payload, or transient Playwright startup failures.
Related errors
- Error evaluating condition: ${{error.message}}
- Container not found: ${config.container_selector}
- Unknown strategy: {strategy_name}
- result.error_message
- str(e)
AI-assisted analysis of unclecode/crawl4ai@7e80152142 (2026-08-14).
Data as JSON: /api/errors/25b91bfbb05dd740.
Report an issue: GitHub.