diff --git a/.changeset/fix-not-listening-error.md b/.changeset/fix-not-listening-error.md new file mode 100644 index 0000000..71a47c0 --- /dev/null +++ b/.changeset/fix-not-listening-error.md @@ -0,0 +1,5 @@ +--- +"@cloudflare/containers": patch +--- + +Fix NOT_LISTENING_ERROR constant to match local-dev runtime error message diff --git a/src/lib/container.ts b/src/lib/container.ts index b10439d..8d2d61a 100644 --- a/src/lib/container.ts +++ b/src/lib/container.ts @@ -24,7 +24,7 @@ const NO_CONTAINER_INSTANCE_ERROR = const RATE_LIMITED_ERROR = 'you are requesting too many containers per second'; const RUNTIME_SIGNALLED_ERROR = 'runtime signalled the container to exit:'; const UNEXPECTED_EXIT_ERROR = 'container exited with unexpected exit code:'; -const NOT_LISTENING_ERROR = 'the container is not listening'; +const NOT_LISTENING_ERROR = 'container is not listening'; const CONTAINER_STATE_KEY = '__CF_CONTAINER_STATE'; const OUTBOUND_CONFIGURATION_KEY = 'OUTBOUND_CONFIGURATION'; diff --git a/src/tests/container.test.ts b/src/tests/container.test.ts index c2e603c..f87b801 100644 --- a/src/tests/container.test.ts +++ b/src/tests/container.test.ts @@ -74,6 +74,31 @@ describe('Container', () => { expect(mockCtx.container.getTcpPort).toHaveBeenCalledWith(8080); }); + test('startAndWaitForPorts should recognise local-dev "not listening" error without leading "the"', async ({ + mockCtx, + container, + }) => { + // In local dev (wrangler dev) the runtime returns "container is not listening" + // without the leading "the" that production uses. Both variants must be + // recognised so doStartContainer treats the state as benign and returns + // instead of retrying until timeout. + const localDevError = new Error('container is not listening on TCP address 10.0.0.1:8080'); + const fetchMock = vi + .fn() + .mockRejectedValueOnce(localDevError) + .mockResolvedValue(new Response('ok')); + mockCtx.container.getTcpPort.mockReturnValue({ fetch: fetchMock }); + + await container.startAndWaitForPorts(8080); + + expect(mockCtx.container.getTcpPort).toHaveBeenCalledWith(8080); + // Exactly 2 calls: doStartContainer recognises the error and returns + // immediately (1 call), then waitForPort succeeds on its first attempt + // (1 call). Without the fix the error is not recognised, doStartContainer + // retries, and the count rises to 3+. + expect(fetchMock).toHaveBeenCalledTimes(2); + }); + test('startAndWaitForPorts should surface rate-limited startup errors on the final retry', async ({ mockCtx, container,