GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — quic: write desired size needs update on maxstream by martenrichter · Pull Request #64768 · nodejs/node

Conversation

@martenrichter

@martenrichter martenrichter commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Without this update the streams can stall, if the chunks are close or bigger than the window size.
It was provoked by a very special timing, so probably hard to test,
Though I do not know, if this is also required for max data of the whole session.
Upstream says no:
ngtcp2/ngtcp2#2243

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@martenrichter
quic: write desired size needs update on maxstream
83e4cb2
Without this update the streams can stall, if the
chunks are close or bigger than the window size.

Signed-off-by: Marten Richter <[email protected]>
@nodejs-github-bot

nodejs-github-bot commented Jul 26, 2026

Copy link
Copy Markdown
Collaborator

Review requested:

  • @nodejs/quic
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@nodejs-github-bot nodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. needs-ci PRs that need a full CI run. quic Issues and PRs related to the QUIC transport implementation. labels Jul 26, 2026
@martenrichter

martenrichter commented Jul 26, 2026

Copy link
Copy Markdown
Contributor Author

@jasnell @pimterry can you have a look?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@martenrichter
quic: Fix lint
cffb9bc
@avivkeller

avivkeller commented Jul 26, 2026

Copy link
Copy Markdown
Member

Can you add a test?

bjohansebas reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@codecov

codecov Bot commented Jul 26, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.14%. Comparing base (9024119) to head (ad505ca).
⚠️ Report is 411 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #64768      +/-   ##
==========================================
- Coverage   90.15%   90.14%   -0.01%     
==========================================
  Files         743      746       +3     
  Lines      242407   242660     +253     
  Branches    45645    45723      +78     
==========================================
+ Hits       218532   218750     +218     
- Misses      15357    15425      +68     
+ Partials     8518     8485      -33     

see 55 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@martenrichter

martenrichter commented Jul 27, 2026

Copy link
Copy Markdown
Contributor Author

Can you add a test?

Not really. I found it in my webtransport test suite. But there it happens only, if I use node.js server and client. If I choose a Quiche client and a Node.js server, or a Node.js client and a Quiche server, it does not surface, as it depends on the particular packet size the particular Quic internals are generating at the low level. But I will later port all of my wt tests over, but therefore wt must be ready. (But this must not mean that these would reliably trigger the issue).

avivkeller reacted with thumbs up emoji avivkeller reacted with eyes emoji
All reactions
  • 👍 1 reaction
  • 👀 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@pimterry

pimterry commented Jul 28, 2026

Copy link
Copy Markdown
Member

Not really. I found it in my webtransport test suite.

I wanted to understand, so I did some digging. I think the trigger is actually quite clear: UpdateWriteDesiredSize was only called on ack, but the stream window is extended independently of acks. A peer can ack all our data, wait (all data acked but zero window available) and then extend the window size to allow more data later - so we do need to update desired size based on the window update alone 👍. Good find @martenrichter! This is tricky to trigger as it's easily obscured by buffering.

We can repro it reliably with something like this:

import { createPrivateKey } from 'node:crypto';
import { readFile } from 'node:fs/promises';
import { setTimeout as sleep } from 'node:timers/promises';
import { listen, connect } from 'node:quic';
import { drainableProtocol } from 'stream/iter';

const keys = 'test/fixtures/keys';
const key = createPrivateKey(await readFile(`${keys}/agent1-key.pem`));
const cert = await readFile(`${keys}/agent1-cert.pem`);

const WINDOW = 4096;
// Fills the window exactly: HTTP/3 spends 11 of those bytes on framing (8 for
// the HEADERS frame below, 3 for the DATA frame header). The send buffer then
// empties at the same moment the window reaches zero, leaving nothing in
// flight to ack. Any other size leaves bytes queued, and the ack for those
// wakes the writer instead, hiding the bug.
const BODY = WINDOW - 11;

let letServerRead;
const serverMayRead = new Promise((resolve) => { letServerRead = resolve; });

const endpoint = await listen((session) => {
  session.onstream = async (stream) => {
    await serverMayRead;
    for await (const _ of stream) { /* reading extends the window */ }
  };
}, {
  sni: { '*': { keys: [key], certs: [cert] } },
  transportParams: {
    initialMaxStreamDataBidiRemote: WINDOW,
    initialMaxData: 1024 * 1024,
  },
  onheaders() { this.sendHeaders({ ':status': '200' }); },
});

const session = await connect(endpoint.address, {
  servername: 'localhost',
  verifyPeer: 'manual',
});
await session.opened;

// Budget well above the window, so the window is what stops the writer.
const stream = await session.createBidirectionalStream({ budget: 1024 * 1024 });
stream.sendHeaders({
  ':method': 'POST',
  ':path': '/',
  ':scheme': 'https',
  ':authority': 'localhost',
}, { terminal: false });

const writer = stream.writer;
writer.writeSync(new Uint8Array(BODY));

// Long enough for every byte to be acked. The peer acks as data arrives,
// whether or not its application has read any of it, so by now the window is
// exhausted, the send buffer is empty, and no further ACK can arrive.
await sleep(500);
console.log('all acked, window exhausted');

const watchdog = setTimeout(() => {
  console.log('STALLED: no drain after MAX_STREAM_DATA');
  process.exit(1);
}, 5000);

letServerRead();                 // extend the window, with no ack attached
console.log('window extended');
await writer[drainableProtocol]();
console.log('writer drain');

clearTimeout(watchdog);
console.log('done');
process.exit(0);

This creates a server which doesn't read, so it'll ack everything without extending the window. The client writes the exact amount to fill the window but leave nothing in its buffers (otherwise the window update triggers more writes, and then gets acks). Then after a 500ms pause, the server reads and triggers a window update.

Fixed client will trigger a drain and complete OK, bad client will stall forever. We should be able to build a test around that directly.

The fix here covers this for HTTP/3, but doesn't totally fix the issue because we have two independent implementations of this with the current application structure, so we'll need to also separately fix the equivalent issue again for pure QUIC in the default app.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@martenrichter

martenrichter commented Jul 28, 2026

Copy link
Copy Markdown
Contributor Author

And we may also need it for session window, but I think we also need a callback from ngtcp2 for this.
Btw. that is the reason why there was so little progress from the last 3 weekends, it was horrible to debug (and I had a second error in the client code that was interfering).

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@martenrichter

martenrichter commented Jul 29, 2026

Copy link
Copy Markdown
Contributor Author

@pimterry I am tring to integrate your test. But actually, the bug I was catching was different; it was actually two buffers, one inside the window size and the other going beyond the window size. At least this what I remember from debugging.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

martenrichter and others added 3 commits July 29, 2026 07:40
@martenrichter @pimterry
quic: add test for maxstreamdata buffer stalls
910daf5
Co-authored-by: Tim Perry <[email protected]>
@martenrichter
quic: rename test
ddb84d6
@martenrichter
quic: fix streamaxdata for non http/3
0db11ea
@martenrichter

martenrichter commented Jul 29, 2026

Copy link
Copy Markdown
Contributor Author

Ok, also done for pure quic.
What is missing though, is the same for maxdata.
So I think we should create a separate issue for this with test, but I do not see a fix, as the ngtcp2 callback is missing.
I am refering to this line:

node/src/quic/streams.cc

Line 1873 in 41525ab

uint64_t conn_left = ngtcp2_conn_get_max_data_left(conn);

it is less likely to cause a stall, but it may happen.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

martenrichter and others added 5 commits July 29, 2026 08:09
@martenrichter
quic: Fix lint
f55f05a
@martenrichter
quic: fix lint
ead7e66
@martenrichter
Fix lint2
43af13b
@martenrichter
Fix lint 3
e71db8b
@martenrichter
Fix lint 4
ad505ca
@martenrichter martenrichter mentioned this pull request Jul 30, 2026
quic: buffer stalls, as maxdata updates do not triggern an update of writeDesired sizes #64835
Open
@martenrichter

martenrichter commented Jul 30, 2026

Copy link
Copy Markdown
Contributor Author

Create a separate issue for maxdata, as I have no clue how to address it currently.
#64835

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@jasnell jasnell added this to QUIC Team Aug 8, 2026
@jasnell jasnell moved this to In Progress in QUIC Team Aug 8, 2026
@jasnell jasnell moved this from In Progress to Ready for Review in QUIC Team Aug 8, 2026
jasnell
jasnell approved these changes Aug 8, 2026
View reviewed changes
@jasnell jasnell added the commit-queue-squash PRs the Commit Queue should land as one squashed commit. label Aug 8, 2026
@nodejs-github-bot

This comment was marked as outdated.

Sign in to view
@nodejs-github-bot

This comment was marked as outdated.

Sign in to view
@nodejs-github-bot

nodejs-github-bot commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

CI: https://ci.nodejs.org/job/node-test-pull-request/76030/

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@trivikr trivikr added commit-queue PRs queued for automated landing through the Commit Queue. and removed commit-queue PRs queued for automated landing through the Commit Queue. labels Aug 20, 2026
@trivikr

trivikr commented Aug 20, 2026

Copy link
Copy Markdown
Member

It looks like this PR is ready to land.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@jasnell jasnell added the commit-queue PRs queued for automated landing through the Commit Queue. label Aug 20, 2026
@jasnell jasnell moved this from Ready for Review to Ready to Land in QUIC Team Aug 20, 2026
@nodejs-github-bot nodejs-github-bot added commit-queue-failed PRs whose Commit Queue landing failed and need manual intervention before retrying. and removed commit-queue PRs queued for automated landing through the Commit Queue. labels Aug 20, 2026
@nodejs-github-bot

nodejs-github-bot commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator
Commit Queue failed
- Loading data for nodejs/node/pull/64768
✔  Done loading data for nodejs/node/pull/64768
----------------------------------- PR info ------------------------------------
Title      quic: write desired size needs update on maxstream (#64768)
   ⚠  Could not retrieve the email or name of the PR author's from user's GitHub profile!
Branch     martenrichter:writedesired -> nodejs:main
Labels     c++, needs-ci, quic, commit-queue, commit-queue-squash
Commits    10
 - quic: write desired size needs update on maxstream
 - quic: Fix lint
 - quic: add test for maxstreamdata buffer stalls
 - quic: rename test
 - quic: fix streamaxdata for non http/3
 - quic: Fix lint
 - quic: fix lint
 - Fix lint2
 - Fix lint 3
 - Fix lint 4
Committers 2
 - Marten Richter <[email protected]>
 - Marten Richter <[email protected]>
PR-URL: https://github.com/nodejs/node/pull/64768
Reviewed-By: James M Snell <[email protected]>
------------------------------ Generated metadata ------------------------------
PR-URL: https://github.com/nodejs/node/pull/64768
Reviewed-By: James M Snell <[email protected]>
--------------------------------------------------------------------------------
   ℹ  This PR was created on Sun, 26 Jul 2026 20:26:23 GMT
   ✔  Approvals: 1
   ✔  - James M Snell (@jasnell) (TSC): https://github.com/nodejs/node/pull/64768#pullrequestreview-4889028017
   ✘  GitHub CI is still running
   ℹ  Last Full PR CI on 2026-08-20T03:22:16Z: https://ci.nodejs.org/job/node-test-pull-request/76030/
- Querying data for job/node-test-pull-request/76030/
✔  Build data downloaded
   ✔  Last Jenkins CI successful
--------------------------------------------------------------------------------
   ✔  Aborted `git node land` session in /home/runner/work/node/node/.ncu
https://github.com/nodejs/node/actions/runs/32384310354
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@martenrichter

martenrichter commented Aug 20, 2026

Copy link
Copy Markdown
Contributor Author

It says: "⚠ Could not retrieve the email or name of the PR author's from user's GitHub profile!"
I wonder what this means. PR worked before for me with node.js .

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@jasnell

jasnell commented Aug 20, 2026

Copy link
Copy Markdown
Member

I wouldn't worry about that. I'll squash and merge these directly.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

jasnell pushed a commit that referenced this pull request Aug 20, 2026
@martenrichter @jasnell
quic: write desired size needs update on maxstream
2bfc1e9
Without this update the streams can stall, if the
chunks are close or bigger than the window size.

Signed-off-by: Marten Richter <[email protected]>
PR-URL: #64768
Reviewed-By: James M Snell <[email protected]>
@jasnell

jasnell commented Aug 20, 2026

Copy link
Copy Markdown
Member

Landed in 2bfc1e9

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@jasnell jasnell closed this Aug 20, 2026
@github-project-automation github-project-automation Bot moved this from Ready to Land to Done in QUIC Team Aug 20, 2026
aduh95 pushed a commit that referenced this pull request Aug 25, 2026
@martenrichter @aduh95
quic: write desired size needs update on maxstream
5d77049
Without this update the streams can stall, if the
chunks are close or bigger than the window size.

Signed-off-by: Marten Richter <[email protected]>
PR-URL: #64768
Reviewed-By: James M Snell <[email protected]>
aduh95 pushed a commit that referenced this pull request Aug 25, 2026
@martenrichter @aduh95
quic: write desired size needs update on maxstream
ec956f2
Without this update the streams can stall, if the
chunks are close or bigger than the window size.

Signed-off-by: Marten Richter <[email protected]>
PR-URL: #64768
Reviewed-By: James M Snell <[email protected]>
@github-actions github-actions Bot mentioned this pull request Aug 25, 2026
2026-08-26, Version 26.8.0 (Current) #65551
Merged
aduh95 pushed a commit that referenced this pull request Aug 27, 2026
@martenrichter @aduh95
quic: write desired size needs update on maxstream
5bf60c7
Without this update the streams can stall, if the
chunks are close or bigger than the window size.

Signed-off-by: Marten Richter <[email protected]>
PR-URL: #64768
Reviewed-By: James M Snell <[email protected]>
@github-actions github-actions Bot mentioned this pull request Sep 7, 2026
2026-09-08, Version 24.21.0 'Krypton' (LTS) #65873
Merged
aduh95 pushed a commit that referenced this pull request Sep 7, 2026
@martenrichter @aduh95
quic: write desired size needs update on maxstream
5187ea3
Without this update the streams can stall, if the
chunks are close or bigger than the window size.

Signed-off-by: Marten Richter <[email protected]>
PR-URL: #64768
Reviewed-By: James M Snell <[email protected]>
aduh95 pushed a commit that referenced this pull request Sep 7, 2026
@martenrichter @aduh95
quic: write desired size needs update on maxstream
18a7ccf
Without this update the streams can stall, if the
chunks are close or bigger than the window size.

Signed-off-by: Marten Richter <[email protected]>
PR-URL: #64768
Reviewed-By: James M Snell <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@jasnell jasnell jasnell approved these changes

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

c++ Issues and PRs that require attention from people who are familiar with C++. commit-queue-failed PRs whose Commit Queue landing failed and need manual intervention before retrying. commit-queue-squash PRs the Commit Queue should land as one squashed commit. needs-ci PRs that need a full CI run. quic Issues and PRs related to the QUIC transport implementation.

Projects

QUIC Team
Status: Done

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

6 participants

@martenrichter @nodejs-github-bot @avivkeller @pimterry @trivikr @jasnell
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.