{"record":{"id":"6e611f4fadcc99f8","repo":"binary-husky/gpt_academic","slug":"error-6e611f","errorCode":null,"errorMessage":"程序终止。","messagePattern":"程序终止。","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"request_llms/bridge_stackclaude.py","lineNumber":262,"sourceCode":"    history_feedin = []\n    for i in range(len(history) // 2):\n        history_feedin.append([history[2 * i], history[2 * i + 1]])\n\n    watch_dog_patience = 5  # 看门狗 (watchdog) 的耐心, 设置5秒即可\n    response = \"\"\n    observe_window[0] = \"[Local Message] 等待Claude响应中 ...\"\n    for response in claude_handle.stream_chat(\n        query=inputs,\n        history=history_feedin,\n        system_prompt=sys_prompt,\n        max_length=llm_kwargs[\"max_length\"],\n        top_p=llm_kwargs[\"top_p\"],\n        temperature=llm_kwargs[\"temperature\"],\n    ):\n        observe_window[0] = preprocess_newbing_out_simple(response)\n        if len(observe_window) >= 2:\n            if (time.time() - observe_window[1]) > watch_dog_patience:\n                raise RuntimeError(\"程序终止。\")\n    return preprocess_newbing_out_simple(response)\n\n\ndef predict(\n    inputs,\n    llm_kwargs,\n    plugin_kwargs,\n    chatbot,\n    history=[],\n    system_prompt=\"\",\n    stream=True,\n    additional_fn=None,\n):\n    \"\"\"\n    单线程方法\n    函数的说明请见 request_llms/bridge_all.py\n    \"\"\"\n    chatbot.append((inputs, \"[Local Message] 等待Claude响应中 ...\"))","sourceCodeStart":244,"sourceCodeEnd":280,"githubUrl":"https://github.com/binary-husky/gpt_academic/blob/d6bde0fa54373309bd05823a49bda8da019d2c77/request_llms/bridge_stackclaude.py#L244-L280","documentation":"Watchdog of the Slack-relay Claude streaming loop: while iterating claude_handle.stream_chat(...) yields, if time.time() - observe_window[1] exceeds watch_dog_patience (5 s), the loop raises RuntimeError('程序终止。') to kill a stalled generation thread.","triggerScenarios":"stream_chat stops yielding for more than 5 seconds during predict_no_ui_long_connection in request_llms/bridge_stackclaude.py:262 — Slack API hang, rate limiting on the polling loop (get_reply polls every 0.5s), dropped connection, or Claude bot never replying so no yields occur.","commonSituations":"Slack 429 rate limit on conversations_history polling; Slack outage; the Claude Slack bot stuck in 'Typing…' forever; user token losing access mid-session.","solutions":["Retry the request; transient Slack rate limits clear quickly","Check Slack API status and auth.test the token to rule out revocation","Reduce polling frequency in get_reply (sleep > 0.5s) or add jitter to avoid 429s","If replies legitimately take >5s to first token, raise watch_dog_patience locally"],"exampleFix":"# before\nwatch_dog_patience = 5\n\n# after\nwatch_dog_patience = 60  # Slack relay has high first-token latency","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    for r in claude_handle.stream_chat(...):\n        observe_window[0] = r\nexcept RuntimeError as e:\n    if str(e) == '程序终止。' and retries_left:\n        retries_left -= 1\n        continue  # rebuild handle and retry\n    raise","preventionTips":["Treat Slack relay first-token latency as seconds-to-minutes; size watchdog accordingly","Watch for Slack 429 in get_reply and back off before the watchdog trips","Recreate ClaudeHandle after a watchdog kill; a dead handle will keep failing"],"tags":["timeout","watchdog","slack","rate-limit","claude-bridge"],"backgroundTag":null,"analyzedSha":"d6bde0fa54373309bd05823a49bda8da019d2c77","analyzedAt":"2026-08-14T22:48:35.038Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}