unclecode/crawl4ai · error · HookValidationError
too many hooks (max 10)
Error message
too many hooks (max 10)
What it means
build_declarative_hooks raises HookValidationError('too many hooks (max 10)') when the declarative spec list exceeds 10 entries. The cap bounds config size and per-page overhead since every hook runs on each matching page event.
Source
Thrown at deploy/docker/hook_registry.py:205
"hook_point": "before_retrieve_html",
"params_model": WaitForTimeoutParams,
"factory": _factory_wait_for_timeout,
"description": "Wait a bounded number of milliseconds before retrieving HTML.",
},
}
def build_declarative_hooks(specs: List[Any]) -> Dict[str, Callable]:
"""Validate declarative hook specs and return {hook_point: composed async hook}.
Each spec is an object/dict with `action` and `params`. Multiple specs that
target the same hook point are composed and run in order. Raises
HookValidationError on an unknown action or invalid params.
"""
if not specs:
return {}
if len(specs) > 10:
raise HookValidationError("too many hooks (max 10)")
grouped: Dict[str, List[Callable]] = {}
for spec in specs:
action = spec.get("action") if isinstance(spec, dict) else getattr(spec, "action", None)
raw_params = (spec.get("params", {}) if isinstance(spec, dict) else getattr(spec, "params", {})) or {}
entry = HOOK_REGISTRY.get(action)
if entry is None:
raise HookValidationError(
f"unknown hook action {action!r}; allowed: {sorted(HOOK_REGISTRY)}"
)
try:
params = entry["params_model"](**raw_params)
except Exception as e:
raise HookValidationError(f"invalid params for hook '{action}': {e}")
sub_hook = entry["factory"](params)
grouped.setdefault(entry["hook_point"], []).append(sub_hook)
hooks: Dict[str, Callable] = {}View on GitHub (pinned to 7e80152142)
Solutions
- Consolidate specs: one block_resources spec accepts a list of resource types; one set_headers spec accepts up to 20 headers.
- Delete hooks you no longer need rather than commenting them out in generated config.
- If the workflow truly needs more, request a raise of the cap or run two crawl jobs.
Example fix
# before
hooks = [{"action": "block_resources", "params": {"resource_types": ["image"]}},
{"action": "block_resources", "params": {"resource_types": ["font"]}}, ... # 11 specs
# after
hooks = [{"action": "block_resources", "params": {"resource_types": ["image", "font", "media", "stylesheet"]}}] Defensive patterns
Strategy: validation
Validate before calling
def valid_hook_count(specs) -> bool:
return isinstance(specs, list) and len(specs) <= 10 Type guard
def is_within_hook_cap(specs) -> bool:
return not specs or len(specs) <= 10 Try / catch
try:
hooks = build_declarative_hooks(specs)
except HookValidationError as e:
if "too many hooks" in str(e):
specs = merge_same_action_specs(specs) # e.g. fold block_resources lists
else:
raise Prevention
- Merge specs targeting the same action before submit.
- Assert len(hooks) <= 10 in config-generation tests.
- Delete obsolete hooks from templates instead of accumulating them.
When it happens
Trigger: Posting a crawl config whose hooks array contains 11 or more {action, params} specs.
Common situations: Generated configs that enumerate per-domain hooks; accumulating hooks across merges/patches until the list grows past 10; teams unaware the limit counts ALL hooks, not per hook point.
Related errors
- unknown hook action {action!r}; allowed: {sorted(HOOK_REGIST
- invalid params for hook '{action}': {e}
- Invalid source(s): {invalid}. Valid: {VALID_SOURCES}
- Hook '{hook_name}' must be a callable function, got {type(ho
- unsupported resource_types {bad}; allowed: {sorted(_ALLOWED_
AI-assisted analysis of unclecode/crawl4ai@7e80152142 (2026-08-14).
Data as JSON: /api/errors/32fed0f979bcbdee.
Report an issue: GitHub.