Skip to content

Dulwich sending unborn to a server not supporting it #2104

@Lordshinjo

Description

@Lordshinjo

Using dulwich 1.1.0 with Gerrit 3.12.2, dulwich is sending a unborn packet while cloning a repository, much to the confusion of the server.

Here's a log of what happens:

Details
2026-02-27 21:20:37,463:urllib3.connectionpool:https://[snip]:443 "GET /a/[snip]/info/refs?service=git-upload-pack HTTP/1.1" 200 113
2026-02-27 21:20:37,464:dulwich.protocol:git< b'version 2'
2026-02-27 21:20:37,465:dulwich.protocol:git< b'ls-refs'
2026-02-27 21:20:37,465:dulwich.protocol:git< b'fetch=shallow'
2026-02-27 21:20:37,465:dulwich.protocol:git< b'server-option'
2026-02-27 21:20:37,465:dulwich.protocol:git< b'agent=JGit/v7.4.0.202507080956-m1-15-g010858e24'
2026-02-27 21:20:37,466:dulwich.protocol:git< 0000
2026-02-27 21:20:37,741:urllib3.connectionpool:https://[snip]:443 "POST /a/[snip]/git-upload-pack HTTP/1.1" 200 25
2026-02-27 21:20:37,741:dulwich.protocol:git< b'ERR unexpected unborn'
2026-02-27 21:20:37,741:root:unknown part in pkt-ref: b'unborn'
Traceback (most recent call last):
  File "[snip].py", line 450, in init
    repo = git.clone(
           ^^^^^^^^^^
  File "/[snip]/lib/python3.12/site-packages/dulwich/porcelain/__init__.py", line 1507, in clone
    repo = client.clone(
           ^^^^^^^^^^^^^
  File "/[snip]/lib/python3.12/site-packages/dulwich/client.py", line 1497, in clone
    result = self.fetch(
             ^^^^^^^^^^^
  File "/[snip]/lib/python3.12/site-packages/dulwich/client.py", line 1631, in fetch
    result = self.fetch_pack(
             ^^^^^^^^^^^^^^^^
  File "/[snip]/lib/python3.12/site-packages/dulwich/client.py", line 4660, in fetch_pack
    refs, server_capabilities, url, symrefs, _peeled = self._discover_references(
                                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/[snip]/lib/python3.12/site-packages/dulwich/client.py", line 4433, in _discover_references
    (refs, symrefs, peeled) = read_pkt_refs_v2(proto.read_pkt_seq())
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/[snip]/lib/python3.12/site-packages/dulwich/client.py", line 500, in read_pkt_refs_v2
    for pkt in pkt_seq:
               ^^^^^^^
  File "/[snip]/lib/python3.12/site-packages/dulwich/protocol.py", line 526, in read_pkt_seq
    pkt = self.read_pkt_line()
          ^^^^^^^^^^^^^^^^^^^^
  File "/[snip]/lib/python3.12/site-packages/dulwich/protocol.py", line 458, in read_pkt_line
    raise HangupException
dulwich.errors.HangupException: The remote server unexpectedly closed the connection.

The unborn packet sending was added in #2074, where unborn support is determined in the following code:

dulwich/dulwich/client.py

Lines 457 to 460 in f8f714b

# Check if server supports unborn refs
supports_unborn = any(
b"ls-refs=unborn" in cap or b"ls-refs" in cap for cap in server_capabilities
)

Here the server only sent ls-refs and not ls-refs=unborn.
Would it make more sense to either avoid sending unborn if the server does not advertise it, or possibly discover it some other way?

Metadata

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