Skip to content

A malformed --file still blames gh for a file the user named #90

Description

@vyncint

Today

$ printf 'not json'                        > nj.json
$ printf '{"data":{}}'                     > nodata.json
$ printf '{"data":{"user":{"login":"x"}}}' > nocal.json
$ : > empty.json
$ for f in nj.json nodata.json nocal.json empty.json; do echo "--- $f"; mossaic --file $f --png o.png </dev/null 2>&1 | head -1; done
--- nj.json
mossaic: unexpected response from gh: expected ident at line 1 column 2
--- nodata.json
mossaic: GitHub returned no user for that login
--- nocal.json
mossaic: unexpected response from gh: missing field `contributionsCollection` at line 1 column 29
--- empty.json
mossaic: unexpected response from gh: EOF while parsing a value at line 1 column 0

$ env PATH=/usr/bin:/bin mossaic --file nj.json --png o.png </dev/null 2>&1 | head -1
mossaic: unexpected response from gh: expected ident at line 1 column 2

Identical with gh off PATH: it is never executed on this path. The tracker's --merge repeats it, one half-step better:

$ mossaic-art VYNCINT --year 2026 --track --merge $PWD/nj.json … | head -1
mossaic-art: could not read "…/nj.json": unexpected response from gh: expected ident at line 1 column 2

The plan loader, two commands away, gets it right:

$ mossaic-art --track --plan $PWD/nj.json --no-colour 2>&1 | head -1
mossaic-art: /…/nj.json is not a mossaic plan: expected ident at line 1 column 2

One shared parse is why: src/github.rs:46 reads the file and hands the body to the same parse the network path uses, whose only wording is format!("unexpected response from gh: {e}") at src/github.rs:98.

Why it is worth fixing--file is the offline entry point the whole test story rests on: install.yml, docs/DESIGN.md §13 and the --snapshot round trip all lean on it. When it goes wrong the user is told their GitHub CLI returned something odd — and, for {"data":{}}, that GitHub has no such login — for a local file they wrote themselves, on a run where gh never ran. They then check gh auth status, the username and the network: everything except the truncated JSON in front of them. --file is also the flag most likely to be handed a file another process is still writing, which is exactly the truncated case. 0.6.3 fixed the neighbour (mossaic --file typo.json now says "could not read typo.json: No such file or directory") and stopped at the missing-file case.

To be accurate about the standard: there is no written rule anywhere in AGENTS.md, CONTRIBUTING.md or docs/DESIGN.md about error messages naming the right subsystem. The case here is the factual one — the message names a subprocess that did not run — plus the inconsistency with the project's own plan loader.

Fix — give github::from_file its own wording instead of reusing the fetch's. Thread the source through parse — an enum of Gh or File(path) is enough — so the messages read mossaic: <path> is not a saved contributions response: expected ident at line 1 column 2 and mossaic: <path> holds no user — a saved response has data.user, and drop the "from gh" phrasing from the chart's and the tracker's file paths. Mirror the plan loader, which already does this well. While there, --merge quotes the path where every other path message does not; make them agree.

Done whenmossaic --file on a non-JSON file, an empty file, a truncated file and a valid-JSON-wrong-shape file each name the path, do not mention gh, and exit 2; the same four through mossaic-art --merge do too; and a test asserts that for a file-sourced parse failure the path appears in the message and the substring "gh" does not.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinggood first issueGood for newcomers

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions