Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/metal-workers-exit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@livekit/agents": patch
---

Fix worker cleanup after LiveKit connection retries are exhausted.
32 changes: 32 additions & 0 deletions agents/src/worker.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// SPDX-FileCopyrightText: 2026 LiveKit, Inc.
//
// SPDX-License-Identifier: Apache-2.0
import { describe, expect, it, vi } from 'vitest';
import { AgentServer, ServerOptions } from './worker.js';

vi.mock('./inference/_warmup.js', () => ({
_getLocalInferenceModule: () => undefined,
}));

describe('AgentServer connection failures', () => {
it('run rejects when connection retries are exhausted', async () => {
const server = new AgentServer(
new ServerOptions({
agent: 'test-agent.js',
wsURL: 'ws://127.0.0.1:1',
apiKey: 'devkey',
apiSecret: 'devsecret',
maxRetry: 0,
numIdleProcesses: 0,
simulation: true,
}),
);

try {
await expect(server.run()).rejects.toThrow(/failed to connect/);
} finally {
await server.close();
await server.close();
}
});
});
15 changes: 11 additions & 4 deletions agents/src/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -491,8 +491,15 @@ export class AgentServer {
if (this.#httpServer) {
tasks.push(this.#httpServer.run());
}
await ThrowsPromise.all(tasks);
this.#close.resolve();
try {
await ThrowsPromise.all(tasks);
this.#close.resolve();
} catch (e) {
if (!this.#close.done) {
this.#close.reject(e instanceof Error ? e : new Error(String(e)));
}
throw e;
}
}

get id(): string {
Expand Down Expand Up @@ -925,7 +932,7 @@ export class AgentServer {

async close() {
if (this.#closed) {
await this.#close.await;
await this.#close.await.catch(() => undefined);
return;
}

Expand All @@ -939,7 +946,7 @@ export class AgentServer {
await ThrowsPromise.allSettled(this.#tasks);

this.#session?.close();
await this.#close.await;
await this.#close.await.catch(() => undefined);
}
}

Expand Down
Loading