{"record":{"id":"706a4432813dffec","repo":"binary-husky/gpt_academic","slug":"json-706a44","errorCode":null,"errorMessage":"Json解析不合常规","messagePattern":"Json解析不合常规","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"request_llms/bridge_ollama.py","lineNumber":116,"sourceCode":"                    # 判定为数据流的结束，gpt_replying_buffer也写完了\n                    logger.info(f'[response] {result}')\n                    break\n                result += chunkjson['message'][\"content\"]\n                if not console_silence: print(chunkjson['message'][\"content\"], end='')\n                if observe_window is not None:\n                    # 观测窗，把已经获取的数据显示出去\n                    if len(observe_window) >= 1:\n                        observe_window[0] += chunkjson['message'][\"content\"]\n                    # 看门狗，如果超过期限没有喂狗，则终止\n                    if len(observe_window) >= 2:\n                        if (time.time()-observe_window[1]) > watch_dog_patience:\n                            raise RuntimeError(\"用户取消了程序。\")\n            except Exception as e:\n                chunk = get_full_error(chunk, stream_response)\n                chunk_decoded = chunk.decode()\n                error_msg = chunk_decoded\n                logger.error(error_msg)\n                raise RuntimeError(\"Json解析不合常规\")\n    return result\n\n\ndef predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_prompt='', stream = True, additional_fn=None):\n    \"\"\"\n    发送至chatGPT，流式获取输出。\n    用于基础的对话功能。\n    inputs 是本次问询的输入\n    top_p, temperature是chatGPT的内部调优参数\n    history 是之前的对话列表（注意无论是inputs还是history，内容太长了都会触发token数量溢出的错误）\n    chatbot 为WebUI中显示的对话列表，修改它，然后yield出去，可以直接修改对话界面内容\n    additional_fn代表点击的哪个按钮，按钮见functional.py\n    \"\"\"\n    if inputs == \"\":     inputs = \"空空如也的输入栏\"\n    user_input = inputs\n    if additional_fn is not None:\n        from core_functional import handle_core_functionality\n        inputs, history = handle_core_functionality(additional_fn, inputs, history, chatbot)","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/binary-husky/gpt_academic/blob/d6bde0fa54373309bd05823a49bda8da019d2c77/request_llms/bridge_ollama.py#L98-L134","documentation":"Catch-all error from bridge_ollama.predict_no_ui_long_connection: any exception while decoding a stream chunk (JSONDecodeError, KeyError on chunkjson['message']['content'], decode errors) falls into the except block, which drains the response via get_full_error for the real server message, logs it, and re-raises this generic RuntimeError. The true cause is in the logged error_msg, not the exception text.","triggerScenarios":"Ollama returning a non-JSON chunk (error page, proxy HTML); a chunk JSON without the 'message'/'content' keys (e.g. an error event frame); connection cut mid-chunk producing truncated bytes; wrong OLLAMA_API_HOST returning HTML.","commonSituations":"OLLAMA_API_HOST misconfigured or pointing at a reverse proxy that returns 4xx/5xx HTML; Ollama model name typo causing an error frame mid-stream; Ollama version emitting a different stream schema than the 'message.content' shape this bridge expects.","solutions":["Read the logger.error output - it contains the raw chunk_decoded from get_full_error which identifies the real failure","Verify OLLAMA_API_HOST / OLLAMA_URL points at a real Ollama /api/chat endpoint returning SSE JSON","Check the model name in llm_kwargs exists on the Ollama server (ollama list)","Test the same request with curl to inspect the raw stream frames","Upgrade/downgrade Ollama to a version whose stream schema includes message.content in every frame"],"exampleFix":"# before\nexcept Exception as e:\n    ...\n    raise RuntimeError(\"Json解析不合常规\")\n\n# after (surface the cause)\nexcept Exception as e:\n    chunk = get_full_error(chunk, stream_response)\n    raise RuntimeError(f\"Json解析不合常规: {chunk.decode(errors='replace')}\") from e","handlingStrategy":"validation","validationCode":"import requests\nr = requests.get(f\"{OLLAMA_API_HOST}/api/tags\", timeout=5)\nassert r.status_code == 200, f'Ollama endpoint broken: {r.status_code}'\nassert llm_kwargs['llm_model'].replace('ollama-', '') in [m['name'] for m in r.json().get('models', [])]","typeGuard":"def is_valid_ollama_chunk(chunkjson: dict) -> bool:\n    return (\n        isinstance(chunkjson, dict)\n        and isinstance(chunkjson.get('message'), dict)\n        and isinstance(chunkjson['message'].get('content'), str)\n    )","tryCatchPattern":"try:\n    result = predict_no_ui_long_connection(...)\nexcept RuntimeError as e:\n    logging.getLogger().error('ollama stream failed, see logged chunk_decoded above')\n    raise","preventionTips":["Pre-flight check OLLAMA_API_HOST with /api/tags before starting a long job","Verify the model name exists server-side before streaming","Check the logger.error line that precedes this raise - it holds the raw failing payload"],"tags":["ollama","json","streaming","error-handling","parsing"],"backgroundTag":null,"analyzedSha":"d6bde0fa54373309bd05823a49bda8da019d2c77","analyzedAt":"2026-08-14T22:48:35.038Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}