{"record":{"id":"ecb0a52c3cfff1f1","repo":"harry0703/MoneyPrinterTurbo","slug":"llm-provider-returned-an-invalid-response-r","errorCode":null,"errorMessage":"[{llm_provider}] returned an invalid response: \"{response}\"","messagePattern":"\\[(.+?)\\] returned an invalid response: \"(.+?)\"","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"app/services/llm.py","lineNumber":234,"sourceCode":"        if adapter == \"qwen\":\n            import dashscope\n            from dashscope.api_entities.dashscope_response import GenerationResponse\n\n            dashscope.api_key = api_key\n            response = dashscope.Generation.call(\n                model=model_name, messages=[{\"role\": \"user\", \"content\": prompt}]\n            )\n            if response:\n                if isinstance(response, GenerationResponse):\n                    status_code = response.status_code\n                    if status_code != 200:\n                        raise Exception(\n                            f'[{llm_provider}] returned an error response: \"{response}\"'\n                        )\n\n                    return _extract_qwen_generation_text(response)\n                else:\n                    raise Exception(\n                        f'[{llm_provider}] returned an invalid response: \"{response}\"'\n                    )\n            else:\n                raise Exception(f\"[{llm_provider}] returned an empty response\")\n\n        if adapter == \"gemini\":\n            from google import genai\n            from google.genai import types\n\n            http_options = types.HttpOptions(base_url=base_url) if base_url else None\n            generation_config = types.GenerateContentConfig(\n                temperature=0.5,\n                top_p=1,\n                top_k=1,\n                max_output_tokens=2048,\n                safety_settings=[\n                    types.SafetySetting(\n                        category=\"HARM_CATEGORY_HARASSMENT\",","sourceCodeStart":216,"sourceCodeEnd":252,"githubUrl":"https://github.com/harry0703/MoneyPrinterTurbo/blob/1f9f19c2021a68d04df228f33e9099a0c947f6f8/app/services/llm.py#L216-L252","documentation":"Raised in the qwen branch when dashscope.Generation.call() returns a truthy object that is not a dashscope GenerationResponse instance. This is a type-contract failure between the installed dashscope SDK and this code, not a server-side error — the isinstance(response, GenerationResponse) guard tripped.","triggerScenarios":"A dashscope SDK version whose Generation.call returns a different response class (or a dict-like wrapper), a mocked/stubbed dashscope in tests, or a partially imported dashscope where GenerationResponse comes from a different module path than the returned object's class.","commonSituations":"Upgrading or downgrading the dashscope package so api_entities.dashscope_response.GenerationResponse no longer matches the actual return type; test environments with fake dashscope modules; SDK refactor in newer dashscope releases (e.g. new streaming/async APIs returning different types).","solutions":["Pin dashscope to a version known to work with this codebase (check requirements and lockfile) and reinstall: pip install dashscope==<known-good>","Print type(response) and response.__class__.__module__ in a debug run to confirm which class is actually returned","If a newer dashscope intentionally changed the return type, update the isinstance check in app/services/llm.py to use duck-typing (check status_code attribute presence) or the new response class","In tests, patch dashscope.Generation.call to return a real GenerationResponse instance, not a plain object"],"exampleFix":"# before\nif isinstance(response, GenerationResponse):\n    ...\nelse:\n    raise Exception(f'[{llm_provider}] returned an invalid response: \"{response}\"')\n\n# after (duck-type on the fields actually used)\nif isinstance(response, GenerationResponse) or hasattr(response, \"status_code\"):\n    ...\nelse:\n    raise TypeError(\n        f\"[qwen] unexpected dashscope response type: {type(response).__name__}; \"\n        \"check dashscope SDK version\"\n    )","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"def is_dashscope_generation_response(resp) -> bool:\n    from dashscope.api_entities.dashscope_response import GenerationResponse\n    return isinstance(resp, GenerationResponse) or (\n        hasattr(resp, \"status_code\") and hasattr(resp, \"output\")\n    )","tryCatchPattern":"except Exception: — treat as a non-retryable SDK-compatibility failure; report dashscope version and switch provider or pin the SDK rather than retrying","preventionTips":["Pin the dashscope version in requirements/lockfile so the response contract cannot drift","Add a smoke test that calls dashscope.Generation.call once after dependency upgrades","In tests, always mock with real GenerationResponse instances"],"tags":["llm","qwen","dashscope","version-compatibility","type-error"],"backgroundTag":null,"analyzedSha":"1f9f19c2021a68d04df228f33e9099a0c947f6f8","analyzedAt":"2026-08-14T19:41:05.568Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}