unclecode/crawl4ai · error · HookValidationError

invalid params for hook '{action}': {e}

Error message

invalid params for hook '{action}': {e}

What it means

build_declarative_hooks wraps pydantic validation of each spec's params: if entry['params_model'](**raw_params) raises (missing required field, out-of-range value, unknown field, or one of the field_validator errors like bad resource types or header checks), it re-raises as HookValidationError("invalid params for hook '<action>': <pydantic message>"). The inner message identifies the exact field problem.

Source

Thrown at deploy/docker/hook_registry.py:219

    """
    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] = {}
    for hook_point, sub_hooks in grouped.items():
        def _compose(sub_hooks):
            async def composed(page, **kwargs):
                for fn in sub_hooks:
                    await fn(page, **kwargs)
                return page
            return composed
        hooks[hook_point] = _compose(sub_hooks)
    return hooks


def describe_registry() -> dict:
    """Enumerate the available declarative actions for /hooks/info."""
    return {

View on GitHub (pinned to 7e80152142)

Solutions

  1. Parse the pydantic detail after the colon — it names the field and the constraint (e.g. 'timeout_ms: Input should be at most ...').
  2. Re-check the params schema for that action in hook_registry.py (the *_Params model) and conform the spec.
  3. Validate specs client-side with the same constraints before submitting the crawl job.

Example fix

# before
{"action": "wait_for_timeout", "params": {"timeout_ms": 999999999}}

# after
{"action": "wait_for_timeout", "params": {"timeout_ms": 5000}}
Defensive patterns

Strategy: try-catch

Validate before calling

from hook_registry import HOOK_REGISTRY

def validate_spec(spec: dict):
    entry = HOOK_REGISTRY.get(spec.get("action"))
    if entry is None:
        raise ValueError(f"unknown action {spec.get('action')!r}")
    return entry["params_model"](**(spec.get("params") or {}))  # raises early with field detail

Type guard

def has_required_params(spec: dict) -> bool:
    entry = HOOK_REGISTRY.get(spec.get("action"))
    if not entry:
        return False
    required = entry["params_model"].model_fields
    params = spec.get("params") or {}
    return all(k in params for k, f in required.items() if f.is_required())

Try / catch

from hook_registry import build_declarative_hooks, HookValidationError

try:
    hooks = build_declarative_hooks(specs)
except HookValidationError as e:
    # inner pydantic text after ': ' names the field and constraint
    field_err = str(e).split(": ", 1)[-1]
    report_config_error(specs, field_err)

Prevention

When it happens

Trigger: Omitting a required field (e.g. block_resources without resource_types); out-of-range numbers (wait_for_timeout timeout_ms > _MAX_WAIT_MS, scroll_to_bottom delay_ms > _MAX_SCROLL_DELAY_MS); wrong types (string where int expected); passing fields the params model does not define.

Common situations: Hand-written JSON configs with typos or missing keys; defaults assumed from a different version; unit or boundary values exceeding the declared ge/le bounds.

Related errors


AI-assisted analysis of unclecode/crawl4ai@7e80152142 (2026-08-14). Data as JSON: /api/errors/265423dcfc88c7f1. Report an issue: GitHub.