unclecode/crawl4ai · warning · AttributeError

Setting '{name}' is deprecated. {self._UNWANTED_PROPS[name]}

Error message

Setting '{name}' is deprecated. {self._UNWANTED_PROPS[name]}

What it means

CrawlerRunConfig.__setattr__ raises AttributeError when you assign a value to a deprecated property (listed in _UNWANTED_PROPS) that differs from its __init__ default. Assigning the default value is tolerated (for internal init), but any real attempt to set old removed settings is blocked with a pointer to the replacement.

Source

Thrown at crawl4ai/async_configs.py:2055

                return all(results) if results else False
        
        return False


    def __getattr__(self, name):
        """Handle attribute access."""
        if name in self._UNWANTED_PROPS:
            raise AttributeError(f"Getting '{name}' is deprecated. {self._UNWANTED_PROPS[name]}")
        raise AttributeError(f"'{self.__class__.__name__}' has no attribute '{name}'")

    def __setattr__(self, name, value):
        """Handle attribute setting."""
        # TODO: Planning to set properties dynamically based on the __init__ signature
        sig = inspect.signature(self.__init__)
        all_params = sig.parameters  # Dictionary of parameter names and their details

        if name in self._UNWANTED_PROPS and value is not all_params[name].default:
            raise AttributeError(f"Setting '{name}' is deprecated. {self._UNWANTED_PROPS[name]}")
        
        super().__setattr__(name, value)

    @staticmethod
    def from_kwargs(kwargs: dict) -> "CrawlerRunConfig":
        # Auto-deserialize any dict values that use the {"type": ..., "params": ...}
        # serialization format (e.g. from JSON API requests or dump()/load() roundtrips).
        # This covers markdown_generator, extraction_strategy, content_filter, etc.
        kwargs = {
            k: from_serializable_dict(v) if isinstance(v, dict) and "type" in v else v
            for k, v in kwargs.items()
        }
        # Only pass keys present in kwargs so that __init__ defaults (and
        # set_defaults() overrides) are respected for missing keys.
        valid = inspect.signature(CrawlerRunConfig.__init__).parameters.keys() - {"self"}
        return CrawlerRunConfig(**{k: v for k, v in kwargs.items() if k in valid})

    # Create a funciton returns dict of the object

View on GitHub (pinned to 7e80152142)

Solutions

  1. Follow the deprecation message and set the replacement field instead
  2. Filter legacy keys before applying user config: drop keys listed in the deprecation map
  3. Temporarily pin the previous crawl4ai version if immediate migration is not feasible

Example fix

// before
cfg.old_setting = True  # removed in upgrade
// after
cfg.new_setting = True   # per deprecation message
Defensive patterns

Strategy: validation

Validate before calling

UNWANTED = set(CrawlerRunConfig._UNWANTED_PROPS)
for k in list(vars(cfg)):
    pass
# before applying external settings:
def safe_set(cfg, k, v):
    if k in CrawlerRunConfig._UNWANTED_PROPS:
        raise DeprecationWarning(f"{k} was removed; see docs")
    setattr(cfg, k, v)

Type guard

def settable(cfg, name: str) -> bool:
    return name not in CrawlerRunConfig._UNWANTED_PROPS

Try / catch

try:
    cfg.old_setting = value
except AttributeError as e:
    if "deprecated" in str(e):
        migrate_setting(cfg, old=name, new=REPLACEMENTS[name])
    else:
        raise

Prevention

When it happens

Trigger: cfg.removed_prop = value on an upgraded install; porting old scripts that configure removed options; kwargs-splatting a legacy dict onto the config object.

Common situations: Version upgrades where old settings moved to cache_mode, content_filter, or LinkPreviewConfig-style nested configs; stale user-supplied config dicts.

Related errors


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