Skip to content

One branch whose name isn't valid UTF-8 makes every /state and /branches request for that repository fail with 502 refs-unreadable #114

Closed

Description

@matt-edmondson

What's wrong

RefResolver.ListAsync (RefResolver.cs L24-L40) runs git for-each-ref --format='%(objectname) %(refname)' refs/heads/ through GitRunner. GitRunner decodes stdout with strict UTF-8 (GitRunner.cs L40ff), so a single invalid byte turns the whole result into a failure. ListAsync then returns null, and both handlers answer 502 refs-unreadable (BranchStateHandler.cs L177 and around L427-L432).

Git doesn't require ref names to be UTF-8. Anyone who can push can create one, for example a branch named in Latin-1 from an older Windows client.

Reproduction

git update-ref "refs/heads/feature/$(printf 'caf\xe9')" HEAD   # in the upstream; git accepts it
git clone --bare --filter=blob:none <upstream> mirror

Calling new RefResolver(new GitRunner(opts), opts).ListAsync("mirror") returns null. From then on, every /state and /branches request for that repository returns 502, including requests whose patterns never match the bad branch. The repository stays down until someone deletes the branch upstream. Clone, fetch and admission all keep succeeding, because admission discards stdout since #50, so nothing points at the cause.

Relation to #50

Closed #50 described this exact symptom ("RefResolver returns null, and /branches and /state return refs-unreadable"). Its acceptance criteria, and the fix, covered only diff-tree and admission. The ref-listing path still has the same failure.

Suggested fix

  • Read for-each-ref output as raw bytes, or decode it leniently, line by line.
  • Skip refs whose names don't decode as UTF-8, and log a warning naming the repository and the hex of the bad name. Every other branch is still served. (A branch that can't be named in the JSON response can't be served faithfully anyway.)

Acceptance criteria

  • A mirror with a refs/heads/caf\xe9 branch next to main serves /state and /branches for main normally.
  • The bad ref is absent from the results and logged once per listing (or once per fetch).
  • A regression test covers this through the real GitRunner.

Activity

  1. matt-edmondson commented on Nov 1, 2026

    @matt-edmondson
    ContributorAuthor

    Triage


    Generated by Claude Code

  2. added a commit that references this issue on Nov 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions