D4Vinci/Scrapling · warning · AttributeError

You must pass a keyword to configure, current keywords: {cls

Error message

You must pass a keyword to configure, current keywords: {cls.parser_keywords}?

What it means

Raised by BaseFetcher.configure() when called with zero keyword arguments. Because the loop body never runs, the method can't configure anything, so the trailing 'if not kwargs' guard raises AttributeError listing the currently accepted parser keywords. It exists to make silent no-ops (e.g., configure(**empty_dict)) loud.

Source

Thrown at scrapling/engines/toolbelt/custom.py:211

    @classmethod
    def configure(cls, **kwargs):
        """Set multiple arguments for the parser at once globally

        :param kwargs: The keywords can be any arguments of the following: huge_tree, keep_comments, keep_cdata, adaptive, storage, storage_args, adaptive_domain
        """
        for key, value in kwargs.items():
            key = key.strip().lower()
            if hasattr(cls, key):
                if key in cls.parser_keywords:
                    setattr(cls, key, value)
                else:
                    # Yup, no fun allowed LOL
                    raise AttributeError(f'Unknown parser argument: "{key}"; maybe you meant {cls.parser_keywords}?')
            else:
                raise ValueError(f'Unknown parser argument: "{key}"; maybe you meant {cls.parser_keywords}?')

        if not kwargs:
            raise AttributeError(f"You must pass a keyword to configure, current keywords: {cls.parser_keywords}?")

    @classmethod
    def _generate_parser_arguments(cls) -> Dict:
        # Selector class parameters
        # I won't validate Selector's class parameters here again, I will leave it to be validated later
        parser_arguments = dict(
            huge_tree=cls.huge_tree,
            keep_comments=cls.keep_comments,
            keep_cdata=cls.keep_cdata,
            adaptive=cls.adaptive,
            storage=cls.storage,
            storage_args=cls.storage_args,
            adaptive_domain=cls.adaptive_domain,
        )

        return parser_arguments

View on GitHub (pinned to 5d213a2d47)

Solutions

  1. Pass at least one valid keyword: Fetcher.configure(adaptive=True).
  2. Guard dynamic calls: only invoke configure() when your options dict is non-empty.
  3. Validate keys against BaseFetcher.parser_keywords before forwarding.

Example fix

# before
options = {k: v for k, v in cfg.items() if k in wanted}  # may be {}
Fetcher.configure(**options)  # AttributeError when empty

# after
if options:
    BaseFetcher.configure(**options) if all(k in BaseFetcher.parser_keywords for k in options) else log.error('bad keys')
Defensive patterns

Strategy: validation

Validate before calling

if not options:
    logger.debug('no parser options to configure; skipping configure()')
else:
    Fetcher.configure(**options)

Type guard

def is_nonempty_valid_options(options: dict) -> bool:
    from scrapling.engines.toolbelt.custom import BaseFetcher
    return bool(options) and all(k in BaseFetcher.parser_keywords for k in options)

Try / catch

try:
    Fetcher.configure()
except AttributeError as e:
    if 'must pass a keyword' in str(e):
        pass  # nothing to configure
    else:
        raise

Prevention

When it happens

Trigger: Calling Fetcher.configure() with no args; forwarding an empty dict via configure(**{}); building kwargs conditionally and accidentally passing none of them.

Common situations: Dynamic config code that collects options and ends up empty; refactoring away hardcoded options and forgetting to remove the now-empty configure() call; template code that always calls configure.

Related errors


AI-assisted analysis of D4Vinci/Scrapling@5d213a2d47 (2026-08-14). Data as JSON: /api/errors/2ce9f26a9f30a23d. Report an issue: GitHub.