Skip to content

fix(flow-client): ignore a response that has no request to end - #25469

Open
totally-not-ai[bot] wants to merge 3 commits into
mainfrom
fix-endrequest-guard-duplicate-response
Open

fix(flow-client): ignore a response that has no request to end#25469
totally-not-ai[bot] wants to merge 3 commits into
mainfrom
fix-endrequest-guard-duplicate-response

Conversation

@totally-not-ai

@totally-not-ai totally-not-ai Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

What

MessageHandler.endRequestIfResponse now ends the request only when one is active, both in the GWT client (MessageHandler.java) and in the TypeScript port (MessageHandler.ts). When there is no active request it logs a debug message and still stops the loading indicator.

Why

RequestResponseTracker.endRequest() throws IllegalStateException("endRequest called when no request is active"), and the already-seen branch of handleJSON calls endRequestIfResponse for a message it has decided to ignore.

A single client message opens exactly one request, so when the server delivers a second copy of a response the client already handled, the first copy ends the request and the second one hits the unguarded endRequest(). The throw only reaches the uncaught handler, which logs it, so stopLoading() is never called and the loading indicator is left running for that message.

Fixes #25467

Tests

  • MessageHandlerTests.ts now models the tracker as the real one behaves: a request is active when the response arrives, endRequest clears it and throws when nothing is active. A new case re-delivers the same response and asserts it is ignored without a second endRequest, while the loading indicator is still stopped. Without the fix that case fails with endRequest called when no request is active.
  • GwtMessageHandlerTest.TestRequestResponseTracker was likewise made to model the real tracker (active request on arrival, endRequest clears it and throws when there is none, calls counted), and a new case delivers the same response twice and asserts the request is ended once. Previously the stub only overrode endRequest and inherited hasActiveRequest, which is false because startRequest is never called — so after the guard every response in the Java suite would have taken the "no request is active" branch and endRequest would never have been exercised at all.

Note on the GWT suite: it is not wired into the default build (gwt.test.pattern is undefined, so the gwt-test execution matches no test), and running it explicitly fails in this environment before this change as well — all eight cases, including untouched ones, error out while compiling the JUnit module with Rebind result AtmospherePushConnection$Factory could not be found. The new Java case is therefore verified only by javac and by its TypeScript counterpart, which does run and which fails without the guard.

## What

`MessageHandler.endRequestIfResponse` now ends the request only when one
is active, both in the GWT client and in the TypeScript port. When there
is none it logs a debug message and still stops the loading indicator.

## Why

`RequestResponseTracker.endRequest()` throws
`IllegalStateException("endRequest called when no request is active")`,
and the already-seen branch of `handleJSON` calls `endRequestIfResponse`
for a message it has decided to ignore. A single client message opens
exactly one request, so when the server delivers a second copy of a
response the client already handled, the first copy ends the request and
the second one hits the unguarded `endRequest()`. The throw only reaches
the uncaught handler, which logs it, so the loading indicator is left
without its stop for that message.

Fixes #25467

## Tests

`MessageHandlerTests.ts` now models the tracker as the real one behaves:
a request is active when the response arrives, `endRequest` clears it and
throws when nothing is active. A new case re-delivers the same response
and asserts it is ignored without a second `endRequest`, while the
loading indicator is still stopped. Without the fix that case fails with
`endRequest called when no request is active`.
## What

`GwtMessageHandlerTest.TestRequestResponseTracker` now models the real
tracker: a request is active when the response arrives, `endRequest`
clears it and throws when there is none, and the calls are counted. A
new case delivers the same response twice and asserts the request is
ended once. Also reverts the `flow-client/package-lock.json` churn that
an `npm install` in the previous commit picked up.

## Why

The stub only overrode `endRequest` and inherited `hasActiveRequest`,
which is `false` because `startRequest` is never called, so after the
guard every response in the Java suite took the "no request is active"
branch and `endRequest` was never reached at all. The lockfile diff only
dropped the `libc` optional-dependency metadata that newer npm writes,
and is unrelated to this fix.

## Tests

The GWT suite is not wired into the default build (`gwt.test.pattern` is
undefined, so the `gwt-test` execution matches no test), and running it
explicitly fails in this environment before the change as well: all
eight cases, including untouched ones, error out while compiling the
JUnit module with `Rebind result AtmospherePushConnection$Factory could
not be found`. The new case is therefore verified only by javac and by
its TypeScript counterpart in `MessageHandlerTests.ts`, which does run
and which fails without the guard.
} else {
// No request to end, e.g. a duplicate of a response that already ended
// it. endRequest would throw for that.
Console.debug('Received a response while no request is active. Not ending a request.');

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why should this point out that it's not ending a request instead of just logging what happened? It's not updating the database either

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dropped the second sentence, in both clients: the message is now just Received a response while no request is active.

The debug message in `endRequestIfResponse` now states that a response
arrived while no request is active, without also listing what the client
did not do in response to it.
@github-actions github-actions Bot added the +0.0.1 label Sep 3, 2026
@sonarqubecloud

sonarqubecloud Bot commented Sep 3, 2026

Copy link
Copy Markdown

@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Test Results

 1 434 files  ±0   1 518 suites  ±0   1h 36m 8s ⏱️ + 1m 58s
11 867 tests +2  11 800 ✅ +2  67 💤 ±0  0 ❌ ±0 
12 186 runs  +2  12 118 ✅ +2  68 💤 ±0  0 ❌ ±0 

Results for commit 5c86fb8. ± Comparison against base commit af559a8.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Client throws when it receives a response it has already seen

1 participant