{"record":{"id":"a70473b6b6698953","repo":"unclecode/crawl4ai","slug":"concurrency-must-be-positive","errorCode":null,"errorMessage":"concurrency must be positive","messagePattern":"concurrency must be positive","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"crawl4ai/async_configs.py","lineNumber":1199,"sourceCode":"            max_links: Maximum number of links to process (prevents overload)\n            query: Query string for BM25 contextual scoring (optional)\n            score_threshold: Minimum relevance score to include links (0.0-1.0, optional)\n            verbose: Show detailed progress during extraction\n        \"\"\"\n        self.include_internal = include_internal\n        self.include_external = include_external\n        self.include_patterns = include_patterns\n        self.exclude_patterns = exclude_patterns\n        self.concurrency = concurrency\n        self.timeout = timeout\n        self.max_links = max_links\n        self.query = query\n        self.score_threshold = score_threshold\n        self.verbose = verbose\n        \n        # Validation\n        if concurrency <= 0:\n            raise ValueError(\"concurrency must be positive\")\n        if timeout <= 0:\n            raise ValueError(\"timeout must be positive\")\n        if max_links <= 0:\n            raise ValueError(\"max_links must be positive\")\n        if score_threshold is not None and not (0.0 <= score_threshold <= 1.0):\n            raise ValueError(\"score_threshold must be between 0.0 and 1.0\")\n        if not include_internal and not include_external:\n            raise ValueError(\"At least one of include_internal or include_external must be True\")\n    \n    @staticmethod\n    def from_dict(config_dict: Dict[str, Any]) -> \"LinkPreviewConfig\":\n        \"\"\"Create LinkPreviewConfig from dictionary (for backward compatibility).\"\"\"\n        if not config_dict:\n            return None\n        \n        return LinkPreviewConfig(\n            include_internal=config_dict.get(\"include_internal\", True),\n            include_external=config_dict.get(\"include_external\", False),","sourceCodeStart":1181,"sourceCodeEnd":1217,"githubUrl":"https://github.com/unclecode/crawl4ai/blob/7e801521428ee12509994d39151006f64055ebe3/crawl4ai/async_configs.py#L1181-L1217","documentation":"LinkPreviewConfig validates that concurrency is a positive number because it sizes the worker pool for concurrently fetching link previews. Zero or negative concurrency has no meaningful execution semantics, so construction fails immediately.","triggerScenarios":"LinkPreviewConfig(concurrency=0), a negative value, or computing concurrency from a formula (e.g. desired_parallelism - existing) that evaluates to <= 0.","commonSituations":"Deriving concurrency from CPU count or a config file where the key is absent and defaults to 0; disabling previews by setting concurrency=0 instead of omitting the config.","solutions":["Set concurrency to a positive value; 5–20 is typical for link-preview fetching","If you meant to disable link previews, pass link_preview_config=None to CrawlerRunConfig instead of zeroing fields","Guard computed values: max(1, computed_concurrency)"],"exampleFix":"// before\ncfg = LinkPreviewConfig(concurrency=workers - cores)  # can be <= 0\n// after\ncfg = LinkPreviewConfig(concurrency=max(1, workers - cores))","handlingStrategy":"validation","validationCode":"concurrency = max(1, int(concurrency or 5))\ncfg = LinkPreviewConfig(concurrency=concurrency)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Clamp externally sourced numeric configs with max(1, v)","Default concurrency explicitly in config loaders"],"tags":["validation","configuration","link-preview","concurrency"],"backgroundTag":null,"analyzedSha":"7e801521428ee12509994d39151006f64055ebe3","analyzedAt":"2026-08-14T20:46:20.673Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}