{"record":{"id":"8ba6024b3d7d0422","repo":"unclecode/crawl4ai","slug":"llm-returned-empty-script","errorCode":null,"errorMessage":"LLM returned empty script.","messagePattern":"LLM returned empty script\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"crawl4ai/script/c4a_compile.py","lineNumber":380,"sourceCode":"        full_prompt =  f\"{GENERATE_SCRIPT_PROMPT}\\n\\n{user_prompt}\" if mode == \"c4a\" else f\"{GENERATE_JS_SCRIPT_PROMPT}\\n\\n{user_prompt}\"\n        \n        response = perform_completion_with_backoff(\n            provider=llm_config.provider,\n            prompt_with_variables=full_prompt,\n            api_token=llm_config.api_token,\n            json_response=False,\n            base_url=getattr(llm_config, 'base_url', None),\n            **completion_kwargs,\n        )\n        \n        # Extract content from the response\n        raw_response = response.choices[0].message.content.strip()\n\n        # Strip accidental markdown fences (```js … ```)\n        clean = re.sub(r\"^```(?:[a-zA-Z0-9_-]+)?\\s*|```$\", \"\", raw_response, flags=re.MULTILINE).strip()\n\n        if not clean:\n            raise RuntimeError(\"LLM returned empty script.\")\n\n        return clean\n\n\n# Convenience functions for direct use\ndef compile(script: Union[str, List[str]], root: Optional[pathlib.Path] = None) -> CompilationResult:\n    \"\"\"Compile C4A-Script to JavaScript\"\"\"\n    return C4ACompiler.compile(script, root)\n\n\ndef validate(script: Union[str, List[str]]) -> ValidationResult:\n    \"\"\"Validate C4A-Script syntax\"\"\"\n    return C4ACompiler.validate(script)\n\n\ndef compile_file(path: Union[str, pathlib.Path]) -> CompilationResult:\n    \"\"\"Compile C4A-Script file\"\"\"\n    return C4ACompiler.compile_file(path)","sourceCodeStart":362,"sourceCodeEnd":398,"githubUrl":"https://github.com/unclecode/crawl4ai/blob/7e801521428ee12509994d39151006f64055ebe3/crawl4ai/script/c4a_compile.py#L362-L398","documentation":"RuntimeError from the c4a_compile pipeline: the configured LLM returned a response whose content, after stripping whitespace and accidental markdown code fences, is empty. The pipeline refuses to return an empty string as compiled JavaScript because downstream execution would fail confusingly.","triggerScenarios":"Calling the LLM-based C4A-Script compiler (compile via LLM, e.g. LLMCompiler/compile functions) where response.choices[0].message.content is '', whitespace only, or contains nothing but ``` fences. Typical with content-filtered responses, misrouted API endpoints returning empty completions, or a chat model putting output in tool calls / refusal fields instead of content.","commonSituations":"Content filters triggering on the script text, using a reasoning model whose visible content is empty (answer in reasoning channel), wrong base_url pointing at an incompatible API, temperature/max_tokens settings yielding empty completions, or model versions that respond with empty content on system-prompt overflow.","solutions":["Retry the compile call — empty completions from filters or sampling are frequently transient.","Inspect the raw LLM response (log response.choices[0]) to see whether content was moved to a refusal/tool-call field or filtered.","Check llm_config (model name, base_url, provider) matches an API that returns plain text content.","Simplify the input script or split it; overly long or odd prompts can push models into degenerate outputs.","As a last resort, use the deterministic (non-LLM) compiler path compile()/validate() in the same module, which never calls an LLM."],"exampleFix":"# before\njs = llm_compile(script, llm_config=cfg)  # RuntimeError: LLM returned empty script.\n\n# after\nfor attempt in range(3):\n    try:\n        js = llm_compile(script, llm_config=cfg)\n        break\n    except RuntimeError as e:\n        if \"empty script\" not in str(e) or attempt == 2:\n            raise\n# or avoid the LLM entirely:\njs = compile(script)  # deterministic C4A compiler","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"for attempt in range(3):\n    try:\n        js = llm_compile(script, llm_config=cfg)\n        break\n    except RuntimeError as e:\n        if \"empty script\" not in str(e) or attempt == 2:\n            raise\n        logger.warning(f\"Empty LLM response, retry {attempt + 1}/3\")","preventionTips":["Log response.choices[0] on failure to spot content filtering or tool-call-only replies.","Prefer the deterministic compile()/validate() path when you don't need an LLM.","Keep llm_config (model, base_url, provider) verified against a working API before batch compiles."],"tags":["llm","c4a-script","compile","empty-response","runtime-error"],"backgroundTag":null,"analyzedSha":"7e801521428ee12509994d39151006f64055ebe3","analyzedAt":"2026-08-14T20:46:20.673Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}