{"record":{"id":"2a86b69dc091fe9b","repo":"binary-husky/gpt_academic","slug":"api-finish-reason","errorCode":null,"errorMessage":"API异常,请检测终端输出。可能的原因是:{finish_reason}","messagePattern":"API异常,请检测终端输出。可能的原因是:(.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"request_llms/oai_std_model_template.py","lineNumber":238,"sourceCode":"            try:\n                chunk = next(stream_response)\n            except StopIteration:\n                if result == \"\":\n                    raise RuntimeError(f\"获得空的回复，可能原因:{finish_reason}\")\n                break\n            except requests.exceptions.ConnectionError:\n                chunk = next(stream_response)  # 失败了，重试一次？再失败就没办法了。\n            response_text, reasoning_content, finish_reason, decoded_chunk = decode_chunk(chunk)\n            # 返回的数据流第一次为空，继续等待\n            if response_text == \"\" and (reasoning == False or reasoning_content == \"\") and finish_reason != \"False\":\n                continue\n            if response_text == \"API_ERROR\" and (\n                finish_reason != \"False\" or finish_reason != \"stop\"\n            ):\n                chunk = get_full_error(chunk, stream_response)\n                chunk_decoded = chunk.decode()\n                logger.error(chunk_decoded)\n                raise RuntimeError(\n                    f\"API异常,请检测终端输出。可能的原因是:{finish_reason}\"\n                )\n            if chunk:\n                try:\n                    if finish_reason == \"stop\":\n                        if not console_silence:\n                            print(f\"[response] {result}\")\n                        break\n                    result += response_text\n                    if reasoning:\n                        reasoning_buffer += reasoning_content\n                    if observe_window is not None:\n                        # 观测窗，把已经获取的数据显示出去\n                        if len(observe_window) >= 1:\n                            observe_window[0] += response_text\n                        # 看门狗，如果超过期限没有喂狗，则终止\n                        if len(observe_window) >= 2:\n                            if (time.time() - observe_window[1]) > watch_dog_patience:","sourceCodeStart":220,"sourceCodeEnd":256,"githubUrl":"https://github.com/binary-husky/gpt_academic/blob/d6bde0fa54373309bd05823a49bda8da019d2c77/request_llms/oai_std_model_template.py#L220-L256","documentation":"While consuming the OpenAI-compatible SSE stream, if a decoded chunk's response_text equals 'API_ERROR' and the finish_reason condition holds, the code fetches the full error body via get_full_error, logs it with logger.error, and raises RuntimeError('API异常...可能的原因是:{finish_reason}'). The real error body is only in the log; the exception carries just the finish-reason hint.","triggerScenarios":"Upstream relays an error payload that decode_chunk maps to the literal 'API_ERROR' text: invalid request (bad model name), authentication failure, rate limit, or a relay/proxy returning an OpenAI-style error object mid-stream.","commonSituations":"Custom API_URL_ORIGINAL pointing at a relay (e.g. one-api/openai-forward) whose quota is spent; model name not supported by the endpoint; key lacking access to the requested model; version drift where decode_chunk's expectations no longer match the provider's error format.","solutions":["Read the logger.error output — it contains the full decoded error chunk with the provider's message.","Test the same key/model/base-URL with curl to confirm access and quota.","Correct the model name or base URL in config.py to one the provider supports.","If behind a proxy/relay, top up its quota or bypass it."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    result = predict_no_ui_long_connection(...)\nexcept RuntimeError as e:\n    if 'API异常' in str(e):\n        detail = read_last_logged_chunk()  # logger.error captured the full body\n        route_to_key_or_quota_fix(detail)\n    else:\n        raise","preventionTips":["Keep the logger configured so the full error chunk is always captured.","Smoke-test key/model/base-URL combos at startup with a tiny request.","Monitor relay quota if using an aggregator."],"tags":["openai","streaming","api-error","relay","logging"],"backgroundTag":null,"analyzedSha":"d6bde0fa54373309bd05823a49bda8da019d2c77","analyzedAt":"2026-08-14T22:48:35.038Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}