{"record":{"id":"9746c1cafb199476","repo":"binary-husky/gpt_academic","slug":"error-9746c1","errorCode":null,"errorMessage":"用户取消了程序。","messagePattern":"用户取消了程序。","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"request_llms/bridge_claude.py","lineNumber":132,"sourceCode":"        need_to_pass, chunkjson, is_last_chunk = decode_chunk(chunk)\n        if chunk:\n            try:\n                if need_to_pass:\n                    pass\n                elif is_last_chunk:\n                    # logger.info(f'[response] {result}')\n                    break\n                else:\n                    if chunkjson and chunkjson['type'] == 'content_block_delta':\n                        result += chunkjson['delta']['text']\n                        if observe_window is not None:\n                            # 观测窗，把已经获取的数据显示出去\n                            if len(observe_window) >= 1:\n                                observe_window[0] += chunkjson['delta']['text']\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\n    return result\n\ndef make_media_input(history,inputs,image_paths):\n    for image_path in image_paths:\n        inputs = inputs + f'<br/><br/><div align=\"center\"><img src=\"file={os.path.abspath(image_path)}\"></div>'\n    return inputs\n\ndef predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_prompt='', stream = True, additional_fn=None):\n    \"\"\"\n    发送至chatGPT，流式获取输出。\n    用于基础的对话功能。","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/binary-husky/gpt_academic/blob/d6bde0fa54373309bd05823a49bda8da019d2c77/request_llms/bridge_claude.py#L114-L150","documentation":"RuntimeError ('用户取消了程序。') from the Claude bridge's watchdog: while accumulating text from content_block_delta SSE events, the code checks observe_window[1], a UI-fed timestamp, against watch_dog_patience (5 s). If the timestamp goes stale during an active delta, the stream read is aborted as a user cancellation. Same cooperative-cancellation contract as the ChatGPT bridge, applied to Anthropic's event stream.","triggerScenarios":"User presses stop in the Gradio UI while Claude is streaming; UI thread stops refreshing observe_window[1] (tab suspended, Gradio poll stalled); custom caller passes observe_window but never updates element [1] while content_block_delta events keep arriving.","commonSituations":"Deliberate mid-answer stops; mobile browsers backgrounding the page during long Claude generations; slow Anthropic responses combined with an unresponsive UI making the watchdog fire spuriously.","solutions":["If intentional cancellation, simply send a new message.","Keep the UI tab active and responsive so the watchdog keeps being fed.","Custom callers: run a feeder thread updating observe_window[1] = time.time() every second during the whole stream.","For consistently slow networks, increase watch_dog_patience in request_llms/bridge_claude.py."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    result = predict_no_ui_long_connection(inputs, llm_kwargs, history, sys_prompt, observe_window=win)\nexcept RuntimeError as e:\n    if '用户取消了程序' in str(e) and not user_cancelled:\n        diagnose_ui_feeding()  # watchdog fired without a stop -> feed loop broken\n    else:\n        raise","preventionTips":["Run the observe_window[1] feeder thread for the full stream duration.","Stop the feeder cleanly when the request completes or errors.","Keep the Gradio tab active during Claude generations.","Log watchdog firings alongside a cancel flag to detect false positives."],"tags":["watchdog","cancellation","claude","streaming","ui"],"backgroundTag":null,"analyzedSha":"d6bde0fa54373309bd05823a49bda8da019d2c77","analyzedAt":"2026-08-14T22:48:35.038Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}