Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

[Bug] Cancelling retry backoff leaves a referenced timeout alive until the original delay expires

オープン 初心者向け
#4,334 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

難易度
2/5
見積もり時間
1〜3時間
初心者へのやさしさ
76/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
node.js, typescript
領域
backend

調査の方向性

まず packages/agent-core-v2/src/_base/utils/retry.ts を読み、特に sleepForRetry と sleep および abortable の使い方を確認してください。報告には、キャンセル後もタイムアウトが残ることを示す Node.js の再現コードが含まれています。このヘルパーの既存テストを確認し、キャンセルと通常完了のテストを追加してください。キャンセル時に同じ理由で reject され、タイムアウトがクリアされる一方、キャンセルされていない待機は遅延時間の経過後に引き続き完了すれば完了です。

索引モデルが issue の本文から書いたものです。

説明

What version of Kimi Code is running?

Source-level reproduction at current main 44cdf8f4039e2ff20d3fe8a4e7868bd90fd786e1. The affected retry.ts and abort.ts are byte-identical in the latest release tag @moonshot-ai/[email protected] (commit b5e28fd6beac752a2cdcc0ff2f5fdf40e6494fbb). I tested the real source helper, not an installed CLI build.

Which open platform/subscription and model were you using?

Not applicable: offline CPU reproduction, no provider requests or API key.

What platform is your computer?

macOS arm64, Darwin 25.5.0 arm64 arm, Node.js v24.19.0.

What issue are you seeing?

Cancelling sleepForRetry immediately rejects its Promise with the original cancellation reason, but leaves its referenced timeout alive until the original backoff expires. An otherwise idle Node process therefore cannot exit naturally after the caller has already caught the cancellation.

This is not a claim that cancellation fails to reject, that another provider request is sent, or that the complete CLI/TUI is permanently frozen.

What steps can reproduce the bug?

From the repository root at the commit above, run with Node 24.15 or newer. No dependency installation is needed for these two modules:

node --input-type=module <<'JS'
import { sleepForRetry } from './packages/agent-core-v2/src/_base/utils/retry.ts';

const started = performance.now();
const controller = new AbortController();
const reason = new Error('cancel this retry');
const pending = sleepForRetry(650, controller.signal);
controller.abort(reason);
try {
  await pending;
} catch (error) {
  console.log('original reason:', error === reason);
}
console.log('active resources:', process.getActiveResourcesInfo());
console.log('cancelled after ms:', Math.round(performance.now() - started));
process.once('beforeExit', () => {
  console.log('beforeExit after ms:', Math.round(performance.now() - started));
});
JS

Actual output on my machine (non-timer handles can vary):

original reason: true
active resources: [ 'FSReqCallback', 'PipeWrap', 'PipeWrap', 'Timeout' ]
cancelled after ms: 1
beforeExit after ms: 651
What is the expected behavior?

After cancellation, reject promptly with the same reason and clear the pending timeout. With no remaining work, the process should be able to exit without waiting for the cancelled delay. Normal, non-cancelled waits should still complete after their delay.

Additional information
  • The helper creates sleep(delayMs) before racing it with abortable; sleep discards the timer handle. Rejecting the outer Promise does not cancel that timer.
  • Actual callers include full-compaction retries and the opt-in infinite LLM retry path. The issue is the leftover resource, not whether those callers stop retrying.
  • In three fresh control runs, cancellation immediately and one event-loop turn after starting 500ms, 32s and 60s sleeps consistently left one active timeout per cancelled wait. Pre-aborted signals created none; normal completion cleared the timer. Long-delay fixtures explicitly cleaned up the observed handles after measurement.
  • Independent child processes rejected immediately but stayed alive for about 650ms in all runs. Pre-aborted controls and a test-only control that clears the captured timer on abort exited immediately. Native node:timers/promises cancellation also left no pending timer.
  • No repository implementation was changed. No live inference, complete CLI/TUI lifecycle, Windows/Linux, or full-repository test suite was exercised.
  • Related reports #1796, #1860 and #2025 concern rate-limit handling/visibility before cancellation. This reproduces after cancellation has already been caught, without HTTP or provider errors.
  • #2855 addresses delayed cancellation inside provider SDK retries; rejection here is already immediate. The CLI also has a force-exit fallback from #1233, so I am not claiming that every kimi -p run hangs. This report is specifically about the engine helper retaining a referenced timer after cancellation.
Contribution
  • I am willing to submit a PR for this bug fix myself (please wait for maintainer approval in this issue first)
主要言語
TypeScript
スター
7.9k
フォーク
1.3k
平均マージ
1日 12時間
マージ済み PR(30日)
103

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

MoonshotAI/kimi-code のほかの issue

MoonshotAI/kimi-code の issue をすべて見る

似ている issue

TypeScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。