D4Vinci/Scrapling · error · TypeError
Invalid argument type
Error message
Invalid argument type: {e} What it means
validate() converts msgspec ValidationError into TypeError('Invalid argument type: ...') whenever kwargs passed to a session constructor or fetch() do not match the config Struct's types. The chained msgspec message names the exact offending field and expected type, so read the full exception text.
Solutions
- Read the appended msgspec message in the traceback — it names the field, expected type, and constraint that failed
- Coerce config values before passing: int()/bool()/proper dict structures, especially values loaded from files/ENV
- Check field constraints: max_pages 1-50, retries 1-10, retry_delay >= 0, wait_selector_state in the allowed states
Example fix
# before (config loaded from JSON, all strings)
session = StealthySession(headless='true', max_pages='3', cookies='session=abc')
# after
cfg = json.load(open('config.json'))
session = StealthySession(
headless=bool(cfg['headless']),
max_pages=int(cfg['max_pages']),
cookies=[{'name': 'session', 'value': 'abc', 'domain': 'example.com', 'path': '/'}],
) Defensive patterns
Strategy: try-catch
Validate before calling
# coerce before constructing the session
def sanitize(cfg: dict) -> dict:
if 'headless' in cfg: cfg['headless'] = bool(cfg['headless'])
if 'max_pages' in cfg: cfg['max_pages'] = int(cfg['max_pages'])
if 'retries' in cfg: cfg['retries'] = int(cfg['retries'])
assert 1 <= cfg.get('max_pages', 1) <= 50
assert 1 <= cfg.get('retries', 3) <= 10
return cfg Type guard
def kwargs_match_config(cfg: dict) -> bool:
try:
convert({k: v for k, v in cfg.items()}, StealthConfig)
return True
except ValidationError:
return False Try / catch
from msgspec import ValidationError
try:
session = StealthySession(**cfg)
except TypeError as e:
if 'Invalid argument type' in str(e):
# e.__cause__ carries msgspec's field-level detail
log.error('config type error: %s', e.__cause__)
raise
raise Prevention
- Coerce values from JSON/YAML/ENV (strings by default) with int()/bool()/dict() before passing
- Read the chained msgspec ValidationError — it names the exact field and expected type
- Respect constraints: max_pages 1-50, retries 1-10, retry_delay >= 0
- Dry-run configs through msgspec.convert at startup to fail fast
When it happens
Trigger: Passing headless='yes' (string instead of bool), cookies='a=b' (string instead of a list of cookie dicts), max_pages='3' (string), unknown-typed proxy values, or any kwarg whose declared type in PlaywrightConfig/StealthConfig mismatches — including constraint violations like max_pages=0 (must be 1..50) or retries=20 (must be 1..10).
Common situations: Loading config from JSON/YAML/ENV where everything arrives as strings; passing Python primitives where msgspec Structs/typed sequences are required; boundary constraint violations (max_pages, retries, retry_delay).
Related errors
- page_action must be callable, got
- page_setup must be callable, got
- Cannot use 'proxy_rotator' together with 'proxy'. Use…
- CDP URL must use 'ws://', 'wss://', 'http://', or…
- Init script path not found
AI-assisted analysis of D4Vinci/Scrapling@5d213a2d47 (2026-08-14).
Data as JSON: /api/errors/cc7e04e68864b773.
Report an issue: GitHub.
Appendix: source
Thrown at scrapling/engines/_browsers/_validators.py:252
defaults = models_default_values[model]
return {k: v for k, v in params.items() if k not in defaults or v != defaults[k]}
@overload
def validate(params: Dict, model: type[StealthConfig]) -> StealthConfig: ...
@overload
def validate(params: Dict, model: type[PlaywrightConfig]) -> PlaywrightConfig: ...
def validate(params: Dict, model: type[PlaywrightConfig] | type[StealthConfig]) -> PlaywrightConfig | StealthConfig:
try:
# Filter out params with the default values (no need to validate them) to speed up validation
filtered = _filter_defaults(params, model.__name__)
return convert(filtered, model)
except ValidationError as e:
raise TypeError(f"Invalid argument type: {e}") from e
View on GitHub (pinned to 5d213a2d47)