{"record":{"id":"ea632d2bc4058c35","repo":"unclecode/crawl4ai","slug":"failed-to-generate-schema-no-attempts-succeeded","errorCode":null,"errorMessage":"Failed to generate schema: no attempts succeeded","messagePattern":"Failed to generate schema: no attempts succeeded","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"crawl4ai/extraction_strategy.py","lineNumber":1987,"sourceCode":"            if attempt >= max_attempts - 1:\n                return schema\n\n            # Detect repeated schema\n            current_json = json.dumps(schema, sort_keys=True)\n            is_repeated = current_json == prev_schema_json\n            prev_schema_json = current_json\n\n            # Build feedback and extend conversation\n            feedback = JsonElementExtractionStrategy._build_feedback_message(\n                best_result, schema, attempt + 1, is_repeated\n            )\n            messages.append({\"role\": \"assistant\", \"content\": raw})\n            messages.append({\"role\": \"user\", \"content\": feedback})\n\n        # Should not reach here, but return last schema as safety net\n        if last_schema is not None:\n            return last_schema\n        raise Exception(\"Failed to generate schema: no attempts succeeded\")\n\nclass JsonCssExtractionStrategy(JsonElementExtractionStrategy):\n    \"\"\"\n    Concrete implementation of `JsonElementExtractionStrategy` using CSS selectors.\n\n    How it works:\n    1. Parses HTML content with BeautifulSoup.\n    2. Selects elements using CSS selectors defined in the schema.\n    3. Extracts field data and applies transformations as defined.\n\n    Attributes:\n        schema (Dict[str, Any]): The schema defining the extraction rules.\n        verbose (bool): Enables verbose logging for debugging purposes.\n\n    Methods:\n        _parse_html(html_content): Parses HTML content into a BeautifulSoup object.\n        _get_base_elements(parsed_html, selector): Selects base elements using a CSS selector.\n        _get_elements(element, selector): Selects child elements using a CSS selector.","sourceCodeStart":1969,"sourceCodeEnd":2005,"githubUrl":"https://github.com/unclecode/crawl4ai/blob/7e801521428ee12509994d39151006f64055ebe3/crawl4ai/extraction_strategy.py#L1969-L2005","documentation":"Raised at the very end of generate_schema when the attempt loop finished without ever producing a parsed schema — last_schema is None, so the safety net cannot return anything. It means every attempt failed before validation even began (all attempts hit empty responses, API failures, or unrecoverable JSON errors with the repair loop exhausted).","triggerScenarios":"Repeated failures across all max_attempts with validate=True where JSON parse repair never succeeded (each attempt raised before a usable schema was stored in last_schema); or a config combination where attempts immediately error (bad API key producing the error-98 wrapper each time).","commonSituations":"Persistent LLM-side breakage: invalid credentials for the whole run, an endpoint that always returns empty content, or a model that never emits parseable JSON within the attempt budget.","solutions":["Fix the underlying per-attempt failure first — earlier exceptions (96/97/98 shapes) hold the root cause; this error only says all attempts were lost","Increase max_attempts and keep validate=True so the repair loop has room to work","Test the LLM config in isolation with a JSON-output prompt; if it fails there, fix provider/model/credentials before retrying schema generation","Simplify input: pass a smaller, cleaner html sample so the model has an easier job"],"exampleFix":"// before\nschema = await JsonElementExtractionStrategy.generate_schema(\n    html=huge_html, llm_config=cfg, max_attempts=1)  # no attempts succeeded\n\n// after\n# sanity-test the LLM first, then retry with a repair budget\nschema = await JsonElementExtractionStrategy.generate_schema(\n    html=smaller_html, llm_config=cfg, validate=True, max_attempts=5)","handlingStrategy":"retry","validationCode":"# ensure per-attempt LLM health first; this error only means every attempt died\nresp = await aperform_completion_with_backoff(\n    provider=cfg.provider, api_token=cfg.api_token,\n    prompt='Return JSON: {\"ok\": true}', base_url=cfg.base_url)\nimport json\njson.loads(resp.choices[0].message.content)  # strict-JSON capable model?","typeGuard":null,"tryCatchPattern":"try:\n    schema = await JsonElementExtractionStrategy.generate_schema(\n        html=h, llm_config=cfg, validate=True, max_attempts=5)\nexcept Exception as e:\n    if str(e) == \"Failed to generate schema: no attempts succeeded\":\n        log.error(\"all attempts failed — check earlier per-attempt errors for root cause\")\n    raise","preventionTips":["Fix the underlying per-attempt failures (empty responses, parse errors, API errors) — this error is only the aggregate symptom","Give the loop room: validate=True plus a larger max_attempts","Shrink/clean the HTML sample so the model's job is easier"],"tags":["extraction","schema-generation","llm","retry-exhausted"],"backgroundTag":null,"analyzedSha":"7e801521428ee12509994d39151006f64055ebe3","analyzedAt":"2026-08-14T20:46:20.673Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}