anthropics / anthropics/claude-agent-sdk-typescript

Timer leak: scheduleFlush setTimeout not cleared on query completion

Aperta
#113 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub
bug
Lingua principale
Shell
Stelle
1.8k
Fork
226
Metriche di merge delle PR
Nessuna PR unita negli ultimi 30g

Descrizione

## Description

When using the SDK's `query()` function, an internal timer from the batched logging mechanism is not cleared when the query completes or is aborted. This causes test frameworks with resource leak detection (like Deno's test sanitizers) to fail.

## Steps to Reproduce

1. Use Deno with test sanitizers enabled (default)
2. Call `query()` and consume all messages until `end_turn`
3. Call `abortController.abort()` to signal completion
4. Test fails with timer leak

```typescript
Deno.test({
name: "query test",
fn: async () => {
const abortController = new AbortController();
const queryGen = query({
prompt: "Say 'test'",
options: { cwd: "/tmp", abortController },
});

for await (const msg of queryGen) {
if (msg.type === "result") break;
}

abortController.abort();
},
});
```

## Error

```
error: Leaks detected:
- A timer was started in this test, but never completed. This is often caused by not calling `clearTimeout`. The operation was started here:
at setTimeout (node:timers:16:10)
at scheduleFlush (sdk.mjs:12639:20)
at Object.write (sdk.mjs:12649:7)
at logForDebugging (sdk.mjs:12729:20)
at Query.readMessages (sdk.mjs:13605:13)
```

## Root Cause

The `scheduleFlush` function at `sdk.mjs:12639` creates a `setTimeout` for batched logging, but this timer is not cleared when:
- The query generator is fully consumed
- The abort controller is signaled
- The query completes normally

## Suggested Fix

Store the timeout ID and clear it in the cleanup/abort path:

```typescript
let flushTimeoutId: ReturnType | null = null;

function scheduleFlush() {
if (flushTimeoutId) return; // Already scheduled
flushTimeoutId = setTimeout(() => {
flush();
flushTimeoutId = null;
}, FLUSH_DELAY);
}

function cleanup() {
if (flushTimeoutId) {
clearTimeout(flushTimeoutId);
flushTimeoutId = null;
}
flush(); // Flush any pending logs immediately
}
```

## Workaround

For now, we disable Deno's test sanitizers for integration tests:

```typescript
Deno.test({
name: "query test",
sanitizeResources: false,
sanitizeOps: false,
fn: async () => { /* ... */ },
});
```

## Environment

- SDK version: 0.1.75
- Runtime: Deno 2.x
- OS: Linux

Guida per i contributori

Nessuna guida per i contributori indicizzata per questo repository

Valutazione

Questa issue non è ancora stata valutata.

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.