Skip to content

Error negotiating protocol version 2 #1423

Closed
@Lordshinjo

Description

Since 0.22.2, dulwich tries to negotiate Git protocol v2, however when trying to clone a repo (in my case from Gerrit 3.10.1, almost the last version), the cloning fails.
Here's a traceback with version 0.22.4:

Traceback (most recent call last):
  File ".../python3.11/site-packages/dulwich/client.py", line 2435, in _discover_references
    [pkt] = list(proto.read_pkt_seq())
    ^^^^^
ValueError: too many values to unpack (expected 1)

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File ".../test.py", line 1, in <module>
    from dulwich.porcelain import clone; clone("https://(redacted)")
                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ".../python3.11/site-packages/dulwich/porcelain.py", line 584, in clone
    return client.clone(
           ^^^^^^^^^^^^^
  File ".../python3.11/site-packages/dulwich/client.py", line 874, in clone
    result = self.fetch(
             ^^^^^^^^^^^
  File ".../python3.11/site-packages/dulwich/client.py", line 984, in fetch
    result = self.fetch_pack(
             ^^^^^^^^^^^^^^^^
  File ".../python3.11/site-packages/dulwich/client.py", line 2607, in fetch_pack
    refs, server_capabilities, url, symrefs, peeled = self._discover_references(
                                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ".../python3.11/site-packages/dulwich/client.py", line 2437, in _discover_references
    raise GitProtocolError(
dulwich.errors.GitProtocolError: unexpected number of packets received

Note that the same code works when specifying clone(..., protocol_version=1) or clone(..., protocol_version=0).

The problem occurs in https://github.com/jelmer/dulwich/blob/dulwich-0.22.4/dulwich/client.py#L258-L263:

def negotiate_protocol_version(proto):
    pkt = proto.read_pkt_line()
    if pkt == b"version 2\n":
        return 2
    proto.unread_pkt_line(pkt)
    return 0

For some reason pkt is b"version 2" instead of b"version 2\n", so dulwich continues assuming that the server negotiated version 0 and fails as the server sent the version and capabilities instead of the expected single packet # service=....

Doing the following would be enough to fix it, however I'm not sure if this is a case where the server is not following the v2 spec or if dulwich is too strict in its handling (though being more lenient is probably a good thing):

     pkt = proto.read_pkt_line()
-    if pkt == b"version 2\n":
+    if pkt is not None and pkt.strip() == b"version 2":
         return 2

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions