Errors and limits
Error shape
amber-git reports errors in two places:
- Per ref, inside a push. git prints a refused ref update as
! [remote rejected] <ref> -> <ref> (<reason>)and exits non-zero. The other refs in the same push are decided on their own. Reasons you may see:queued for approval by the repo owner (ref <handle>), theamber-ci gate:refusals in Concepts,tags don't move: <ref> exists; ...for a push that moves a tag, and refusals of a delete, such asref moved to <sha>; fetch and retry the delete. - As an HTTP status, with a plain-text body
(
Content-Type: text/plain; charset=utf-8), which git prints afterfatal:orremote:.
Messages are written for people and may change; there are no error codes.
curl -sS https://amber-git.stackwell.tech/nope | grep -Fx 'not found'
Status codes
| Status | Meaning |
|---|---|
200 | Done. |
202 | A re-send to the GitHub mirror was queued. |
400 | A withdraw without a handle, a check of a queued push without a full sha, or an unknown service on info/refs. |
401 | No token, or one amber-git doesn’t accept. Body unauthenticated, with WWW-Authenticate: Basic realm="amber-git" and WWW-Authenticate: Bearer. |
403 | You can’t reach this repository, or a read-only client tried to push. |
404 | No such path, no such repository, or one you can’t reach. Also a file the read routes can’t find (with Amber-Git-Absent: path). |
409 | A withdraw that came too late, or a re-send for a repository that doesn’t mirror. |
410 | The repository was renamed (repository was renamed to <name>) or retired. |
413 | Over a size limit; see below. |
422 | The read routes were asked for a commit no branch or tag reaches. |
502 | A withdraw, or a check of a queued push, couldn’t reach Granite. The push stays queued; retry. |
503 | The server is busy; retry after the Retry-After header (30 seconds). |
Without a valid token, every repository answers 401, whether or not it
exists:
curl -sS -o /dev/null -w '%{http_code}\n' 'https://amber-git.stackwell.tech/any-repo.git/info/refs?service=git-upload-pack' | grep -Fx 401
Rate limits and busy answers
amber-git has no per-caller rate limit. Each push, fetch, clone or file read
reserves memory before it starts. When none is free, the request waits up to
60 seconds (15 seconds for the read routes) and then gets 503 with
Retry-After: 30. A server out of temporary disk answers the same way.
Size limits
| Limit | Value |
|---|---|
| One push, on the wire | 2 GiB; the push is refused |
| One object, uncompressed | 100 MiB; the push is refused |
| Objects in one push | 250,000; the push is refused |
| One fetch or clone request body (what your client sends) | 10 MiB (413) |
| A file from the read route | 1 MiB (413) |
| A tree listing from the read route | 16 MiB (413) |
| Commit and tree data one clone or fetch may read | About 64 MB; past it, refused with a message |
| Commit and tree data one push may read | About 16 MB; past it, refused with a message |
A push over 2 GiB is refused with the reason, as a rejected push:
remote unpack failed: push is over 2048 MB, .... Past 4 GiB the server
stops reading and answers 413. Git may show only RPC failed; curl 55 Send failure: Connection reset by peer, because it is still sending when the
connection closes. Either way nothing from the push is stored.
GET /limits, with any valid token, returns the push, object and walk
limits in force as JSON, so a tool can check a repository before pushing it
without keeping its own copy:
{"max_push_bytes": 2147483648, "max_object_bytes": 104857600,
"max_push_objects": 250000, "max_push_walk_bytes": 134217728,
"max_fetch_walk_bytes": 536870912, "walk_bytes_per_object": 128,
"walk_bytes_per_byte": 8}
A walk is charged walk_bytes_per_object for each distinct commit, tree or
tag it reads, plus walk_bytes_per_byte for each byte of it.
The push and object limits match GitHub’s. A long-running push or fetch is kept alive while the server works; a client that stops sending for 5 minutes is disconnected.