Skip to content

[Bug] Failed to reset USB device: NetworkError (Windows) #2417

Closed

Description

@BertLindeman

Describe the bug
On windows: try to connect via USB to a primehub does not complete the connect.

To reproduce
Steps to reproduce the behavior:

  1. Open labs.pybricks.com
  2. connect the primehub via USB cable.
  3. click the USB connect button
  4. select the hub and click "connect"
  5. expect the USB-button to change to USB-connected and the "Run" and "REPL" buttons to enable.

Expected behavior
See the USB connect change to "connected"
and the "Run" and "REPL" buttons to enable.

Screenshots
There is a saying that a picture is worth a 1000 words. Screenshots really help to identify and solve problems.

Just before click on "Connect"
Image

just after click on "Connect":
Image

Extra info:
labs version (as app on win11 25H2)
"v3.6.1 (Pybricks Beta v2.8.0-beta.2)"

Robot Inventor firmware:
('primehub', '4.0.0a0', 'ci-build-4325-v3.6.1-548-g76893f68 on 2025-10-30')

Also mentionned in PR 405

[EDIT]
The same with the EV3 from the same build.
I do not know how to copy the text from the dev tools, so a picture:

Image

[EDIT 2]
Used:

  • brave
  • chrome
  • edge
  • firefox
    All the same result

Activity

  1. changed the title [-][Bug] USB connection to primehub does not complete[/-] [+][Bug] USB connection to primehub does not complete (Windows)[/+] on Nov 2, 2025
  2. added
    OS: Windows 11Issues that only occur on Windows 11 (or 10)
    software: pybricks-codeIssues with https://code.pybricks.com application
    topic: USBIssues related to USB
    and removed
    triageIssues that have not been triaged yet
    on Dec 5, 2025
  3. added theissue type on Dec 5, 2025
  4. changed the title [-][Bug] USB connection to primehub does not complete (Windows)[/-] [+][Bug] Failed to reset USB device: NetworkError (Windows)[/+] on Dec 5, 2025
  5. laurensvalk commented on Dec 5, 2025

    @laurensvalk
    Member

    Can confirm. Here we can also see that we do get disconnection events.

    Image
  6. dlech commented on Dec 5, 2025

    @dlech
    Member

    It turns out that WINUSB has much more limited features compared to other OSes. So even some functions in the WebUSB implementation, like reset() are not available on Windows.

    I started looking into this a while back but I didn't come up with a solution yet. The reason we were using the reset in the first place is because endpoints have an even/odd thing where every other packet is marked as even (and the rest odd) to catch missed or duplicate packets. If the host and the peripheral get out of sync, it causes an error. The reset is one way to sync these back up.

    Instead, I think we will have to do something with stalls and clearing the stalls on the endpoint to sync them back up.

    pybricksdev has similar issues on Windows for the same reason.

  7. self-assigned this
    on Dec 5, 2025
  8. BertLindeman commented on Dec 5, 2025

    @BertLindeman
    Author

    pybricksdev has similar issues on Windows for the same reason.

    I did not see errors on win 11(25H2) using pybricksdev run usb myprog.py to an EV3,
    but on flash to the same EV3:

        raise RuntimeError(
    RuntimeError: message sequence number mismatch: 256 != 0 
    
  9. dlech commented on Dec 5, 2025

    @dlech
    Member

    RuntimeError: message sequence number mismatch: 256 != 0

    I think that is #2375.

  10. Sirus-7 commented on Dec 7, 2025

    @Sirus-7
    Sponsor

    I can confirm this issue for EV3 on Windows 10 22H2.

  11. laurensvalk commented on Jan 21, 2026

    @laurensvalk
    Member

    Let's try to make some progress here.

    It turns out that WINUSB has much more limited features compared to other OSes. So even some functions in the WebUSB implementation, like reset() are not available on Windows.

    I started looking into this a while back but I didn't come up with a solution yet. The reason we were using the reset in the first place is because endpoints have an even/odd thing where every other packet is marked as even (and the rest odd) to catch missed or duplicate packets. If the host and the peripheral get out of sync, it causes an error. The reset is one way to sync these back up.

    If I remove the problematic part from Pybricks Code:

    -    // Always reset the USB device to ensure it is in a known state.
    -    const [, resetErr] = yield* call(() => maybe(usbDevice.reset()));
    -    if (resetErr) {
    -        // TODO: show error message to user here
    -        console.error('Failed to reset USB device:', resetErr);
    -        yield* put(usbDidFailToConnectPybricks());
    -        yield* cleanup();
    -        return;
    -    }

    Everything still works on my Linux host.

    @dlech: Where are we doing this "even/odd" thing mentioned above? I'd like to try and force the bad case to see if we can recover.

    Instead, I think we will have to do something with stalls and clearing the stalls on the endpoint to sync them back up.

    We do already have timeouts on the send in pbdrv_usb_tx_event which leads to calling pbdrv_usb_tx_reset. Might this be sufficient?

    From what I'm reading, calling reset from the host is somewhat blunt and typically not needed?

    @jaguilar: I think you already have a build environment for Pybricks Code on Windows. Would you be able to try the above patch to see if it fixes connecting/downloading/running on Windows? Thanks!

  12. dlech commented on Jan 21, 2026

    @dlech
    Member

    Where are we doing this "even/odd" thing mentioned above?

    It is in the endpoints. I'm not sure if it is in software or hardware. But clearing a stall/halt should reset just the endpoints.

    There is a 50% chance that if you disconnect and reconnect that the endpoints will be in the right state. So you need a very specific test that does an odd number of packets to trigger the bug. I was able to do this with pybricksdev by downloading and running a program of a specific size.

    From what I'm reading, calling reset from the host is somewhat blunt and typically not needed?

    Yes, there should be other ways around it.

    For example, we could make our own reset command that just resets the endpoints. Search the code for MSC_BOT_Reset to see an example in the STM32 USB library. The Microsoft docs recommended doing something like this.

    We do already have timeouts on the send in pbdrv_usb_tx_event which leads to calling pbdrv_usb_tx_reset. Might this be sufficient?

    This does not reset the endpoints, so no, it is not sufficient. Possibly we could do that, but I don't think it is the right solution.

    Additionally, there is no way for the host computer to know that the hub has timed out and that it needs to re-subscribe. Even if the endpoints were reset, the hub would still stop sending data to the host. The host can't tell the difference between a timeout and just no data. So it is a separate problem that also needs to be fixed.

    We either need to make the timeout not touch USB and only drop stdout data so that we don't block print functions or we need to change how it works and call USBD_LL_StallEP() (or platform equivalent) so that the host knows that the hub timed out and needs to be reset again. Or we could send a "heartbeat" and the host would be responsible for keeping track of that and having it's own timeout and resetting after that.

    I'm a bit in favor of at least trying the first option first since it is much easier to implement. Then we can do some testing to see how often we are dropping messages to see if we need to try something else.

    We need to test things like what if the web page "goes to sleep", does it keep servicing USB? If it stops for a while, do we care that we lost print output during this time?

  13. dlech commented on Jan 21, 2026

    @dlech
    Member

    Or we could consider a drastically different approach.

    I initially discounted the idea of using a USB serial port implementation for a couple of reasons. The main reason is that it is what LEGO uses on SPIKE Prime and we don't want Pybricks hubs showing up in the official LEGO apps and have people complaining to LEGO that it isn't working. And also because serial port data is a stream rather than packet-based, so we would have to do more work to encode and decode packets from a stream.

    Since we are looking at RFCOMM for the Pybricks Profile on Bluetooth Classic, we are going to have to do the extra work for the last point anyway.

    And due to some new information we've learned recently about SPIKE Prime, I think LEGO might have changed their app in a way that might be able to discriminate between a hub running Pybricks or not. We would need to test that to be sure, but that might make the first point no longer a blocker.

    This would move the handling of the endpoints out of the browser, so it could potentially solve some of those issues. I'm not sure how it would handle back-pressure though if the host-side app stopped reading from the serial port. And of course it could have some surprise issues that we don't know about since we haven't done much with Web Serial yet.

    So maybe it could be prudent to try out the RFCOMM implementation first and see how that goes, then come back to USB to make a more informed decision?

  14. jaguilar commented on Jan 22, 2026

    @jaguilar
    Sponsor

    @jaguilar: I think you already have a build environment for Pybricks Code on Windows. Would you be able to try the above patch to see if it fixes connecting/downloading/running on Windows? Thanks!

    I have changed my main OS over to Linux but I do still have a Windows partition. What specific fixes do you want me to try and what is the test protocol (i.e. what action should work with the fixes and won't work without?).

  15. laurensvalk commented on Jan 22, 2026

    @laurensvalk
    Member

    At the moment, connecting to the hub on Windows fails as described in the first two posts above. Apparently because the reset does not work well on Windows. I was curious to see where things stand on Windows otherwise if we skipped the reset:

    diff --git a/src/usb/sagas.ts b/src/usb/sagas.ts
    index 3e9ae654..dd364b43 100644
    --- a/src/usb/sagas.ts
    +++ b/src/usb/sagas.ts
    
    @@ -140,6 +140,8 @@ function* handleUsbConnectPybricks(hotPlugDevice?: USBDevice): Generator {
             usbDevice = hotPlugDevice;
         }
     
    +    yield* delay(100);
    +
         const [, openErr] = yield* call(() => maybe(usbDevice.open()));
         if (openErr) {
             // TODO: show error message to user here
    @@ -151,16 +153,6 @@ function* handleUsbConnectPybricks(hotPlugDevice?: USBDevice): Generator {
     
         exitStack.push(() => usbDevice.close().catch(console.debug));
     
    -    // Always reset the USB device to ensure it is in a known state.
    -    const [, resetErr] = yield* call(() => maybe(usbDevice.reset()));
    -    if (resetErr) {
    -        // TODO: show error message to user here
    -        console.error('Failed to reset USB device:', resetErr);
    -        yield* put(usbDidFailToConnectPybricks());
    -        yield* cleanup();
    -        return;
    -    }
    -
         const [, selectErr] = yield* call(() => maybe(usbDevice.selectConfiguration(1)));
         if (selectErr) {
             // TODO: show error message to user here

    This patch does that. (The 100ms delay here is related to a secondary issue but is worth considering in this test.)


    As David explains above, this isn't necessarily how we'd move forward. But nobody has tested USB connectivity with Pybricks Code on Windows yet. Maybe there are other issues past this point that we don't know about yet, so investigating that would be quite useful.

    A good test scenario here would be to try out the REPL and run a few programs.

  16. laurensvalk commented on Jan 23, 2026

    @laurensvalk
    Member

    Where are we doing this "even/odd" thing mentioned above?

    It is in the endpoints. I'm not sure if it is in software or hardware. But clearing a stall/halt should reset just the endpoints.

    There is a 50% chance that if you disconnect and reconnect that the endpoints will be in the right state. So you need a very specific test that does an odd number of packets to trigger the bug. I was able to do this with pybricksdev by downloading and running a program of a specific size.

    I have tried to reproduce this and kept track of the number of messages we send to the hub, and alternating between making the program just a bit longer to trigger an extra packet.

    So far everything works great without the reset.

    Did you reproduce it back then on Spike or EV3? And do the number of packets from the hub to Pybricks Code matter too?

  17. dlech commented on Jan 23, 2026

    @dlech
    Member

    I was probably using SPIKE Prime + pybricksdev. I'll try to do some more testing this weekend to refresh my memory.

  18. dlech commented on Jan 24, 2026

    @dlech
    Member

    Reproducible case on Linux (didn't try other OS yet) + SPIKE Prime (didn't try EV3/NXT yet):

    • Pybricks MicroPython v4.0.0b4 with PBDRV_CONFIG_USB_CHARGE_ONLY set to 0.
    • pybricksdev v2.3.2 with self._device.reset() commented out in PybricksHubUSB._client_connect().

    Run the command: echo "print('hello')" | pybricksdev run usb -

    First time, works. Second time hangs forever.

  19. dlech commented on Jan 24, 2026

    @dlech
    Member

    I made pybricks/pybricksdev#133 to get rid of the reset in pybricksdev and replace it with just resetting the endpoints (by calling the clear halt function).

    Looking at Wireshark USB capture on Linux, it doesn't appear that we do the same in the browser. When a tab with Pybricks code is closed, there is an extra USB message that I'm guessing is stalling the endpoint. Then we Pybricks Code reconnects, the browser is taking care of the necessary clearing of the stall behind the scenes.

    Anyway, the initial issue here about reset failing on Windows is fixed in pybricks/pybricks-code@3abc3f3. So we can close this issue and start new ones for additional USB bugs we find.

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

Metadata

Metadata

Assignees

Labels

OS: Windows 11Issues that only occur on Windows 11 (or 10)software: pybricks-codeIssues with https://code.pybricks.com applicationtopic: USBIssues related to USB

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions