fj pr list fails on any repo with a Forgejo system user as requested reviewer: negative user ids do not fit u64 #246

Open
opened 2026-08-09 19:53:04 +00:00 by stephen · 0 comments
Owner

fj pr list fails outright on any repo where a PR has a Forgejo system user as a requested reviewer. It has been failing on rasterstate/fj itself, on two machines, with an error that names no field, no PR and no repo:

$ fj pr list --repo rasterstate/fj
error: decoding JSON list response

Root cause

The request succeeds. The deserializer is what fails:

→ GET https://rasterhub.com/api/v1/repos/rasterstate/fj/pulls?state=open&limit=30&page=1
← 200 OK
error: decoding JSON list response
  caused by: invalid value: integer `-2`, expected u64 at line 1 column 1375

The -2 is a user id:

#245  reviewers=[(-2, 'forgejo-actions')]
#243  reviewers=[(-2, 'forgejo-actions')]

forgejo-actions is a Forgejo system account (noreply@forgejo.org, created 1970-01-01). Forgejo uses negative ids for its system and ghost users, and fj types the user id as u64, so any payload containing one is undecodable. Nothing is wrong with the data.

Why this is worse than a broken subcommand

The failure is total and it is silent about its cause. fleet-status reports rasterstate/fj MISSING in the PR queue, which reads identically to "no PRs" or "repo unreachable", so the supervising agent has been blind to every open PR in this repo without knowing it. A gate that fails closed is fine; a gate that fails quiet cannot distinguish "nothing happened" from "nothing was observed".

Two PRs currently trip it, so the blindness is not hypothetical.

Expected

  1. User ids deserialize as a signed integer, so ghost (-1) and system (-2) users parse like any other. This is a data-model fix, not a special case: negative ids are valid Forgejo, not corruption.
  2. The error, when one does occur, names the repo, the endpoint and the field. decoding JSON list response sent me to --debug to learn anything at all.
  • #241 (invalid type: null, expected a sequence on fj pr checks) is closed, and #245 fixes the null-check-status list. Same class of defect: fj's model is stricter than what Forgejo actually returns. Worth a sweep of the response types for other fields that are narrower than the API contract, because these keep surfacing one command at a time.

Reproduction

fj pr list --repo rasterstate/fj          # fails
fj pr list --repo rasterstate/fleet       # succeeds
fj api "repos/rasterstate/fj/pulls?state=open" | grep -n '"id": -'

Reproduced on fj 0.4.1 on usw-dev-01 and on the operator's laptop.

`fj pr list` fails outright on any repo where a PR has a Forgejo system user as a requested reviewer. It has been failing on `rasterstate/fj` itself, on two machines, with an error that names no field, no PR and no repo: ``` $ fj pr list --repo rasterstate/fj error: decoding JSON list response ``` ## Root cause The request succeeds. The deserializer is what fails: ``` → GET https://rasterhub.com/api/v1/repos/rasterstate/fj/pulls?state=open&limit=30&page=1 ← 200 OK error: decoding JSON list response caused by: invalid value: integer `-2`, expected u64 at line 1 column 1375 ``` The `-2` is a user id: ``` #245 reviewers=[(-2, 'forgejo-actions')] #243 reviewers=[(-2, 'forgejo-actions')] ``` `forgejo-actions` is a Forgejo system account (`noreply@forgejo.org`, created `1970-01-01`). **Forgejo uses negative ids for its system and ghost users**, and fj types the user id as `u64`, so any payload containing one is undecodable. Nothing is wrong with the data. ## Why this is worse than a broken subcommand The failure is total and it is silent about its cause. `fleet-status` reports `rasterstate/fj MISSING` in the PR queue, which reads identically to "no PRs" or "repo unreachable", so the supervising agent has been blind to every open PR in this repo without knowing it. A gate that fails closed is fine; a gate that fails *quiet* cannot distinguish "nothing happened" from "nothing was observed". Two PRs currently trip it, so the blindness is not hypothetical. ## Expected 1. User ids deserialize as a signed integer, so ghost (`-1`) and system (`-2`) users parse like any other. This is a data-model fix, not a special case: negative ids are valid Forgejo, not corruption. 2. The error, when one does occur, names the repo, the endpoint and the field. `decoding JSON list response` sent me to `--debug` to learn anything at all. ## Related, not the same - #241 (`invalid type: null, expected a sequence` on `fj pr checks`) is closed, and #245 fixes the null-check-status list. Same **class** of defect: fj's model is stricter than what Forgejo actually returns. Worth a sweep of the response types for other fields that are narrower than the API contract, because these keep surfacing one command at a time. ## Reproduction ``` fj pr list --repo rasterstate/fj # fails fj pr list --repo rasterstate/fleet # succeeds fj api "repos/rasterstate/fj/pulls?state=open" | grep -n '"id": -' ``` Reproduced on fj 0.4.1 on usw-dev-01 and on the operator's laptop.
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
rasterstate/fj#246
No description provided.