mist read: owner/ID form sends request to wrong API path
muse mist read: owner/ID form sends request to wrong API path
Background
muse mist read accepts two input forms:
- Bare ID:
muse mist read H7XFVEzeDfqk - Owner-qualified:
muse mist read gabriel/H7XFVEzeDfqk
The help text and docstring both document the owner/ID form as valid. But when
run_read detects a / in the input, it constructs the wrong API path:
# muse/cli/commands/mist.py:616 — BUG
api_path = f"/api/{owner_part}/mists/{id_part}"
The server has no route at /api/{owner}/mists/{id}. The real route is
GET /api/mists/{mist_id} — owner is not part of the API path. The result is
an HTTP 404 that surfaces to the user as:
❌ Hub returned HTTP 0: Server returned invalid JSON: Expecting value: line 1 column 1 (char 0)
The error message is also misleading: the underlying 404 body is
{"detail": "Not Found"} — valid JSON — but the CLI swallows the HTTP status
and reports a JSON parse failure instead.
Root cause
run_read is the only mist command that got the path wrong. Every other command
that handles owner/ID input correctly discards the owner and routes to
/api/mists/{id}:
| Command | Line | Path built | Correct? |
|---|---|---|---|
run_read |
616 | /api/{owner}/mists/{id} |
❌ bug |
run_delete |
903 | /api/mists/{id} |
✅ |
run_update |
994 | /api/mists/{id} |
✅ |
run_forks |
1053 | /api/mists/{id}/forks |
✅ |
run_raw |
1113 | /api/mists/{id}/raw |
✅ |
run_embed |
811 | /api/{owner}/mists/{id}/embed |
✅ (embed route intentionally needs owner) |
The run_fork command (line 690–696) was also checked — it correctly extracts
just the id_part for /api/mists/{id}/fork.
Goal
muse mist read gabriel/H7XFVEzeDfqk --hub https://staging.musehub.ai --json
returns the mist JSON. Both the bare-ID and the owner/ID form work identically.
Phases
Phase 1 — Fix run_read
One-line change in muse/cli/commands/mist.py.
Deliverable
MR_01— Change line 616:# Before api_path = f"/api/{owner_part}/mists/{id_part}" # After api_path = f"/api/mists/{id_part}"The
owner_partvariable becomes unused; remove the assignment too (lines 613–614 can simplify to extracting onlyid_part).
Phase 2 — Fix the misleading 404 error message
When _hub_api receives a non-2xx response, the caller sees a JSON-parse error
instead of the actual HTTP status. The error should surface the HTTP status code
and the response body so the user can diagnose it.
Deliverable
MR_02—_hub_api(or its caller inrun_read) raises a clear error on non-2xx HTTP:❌ Hub returned HTTP 404: {"detail": "Not Found"}. The current"Server returned invalid JSON"message must not appear for a response that actually contains valid JSON.
Phase 3 — Tests
No test currently exercises run_read with the owner/ID form. Add tests to
prevent regression.
Deliverables
MR_03— Unit test:run_readwith"gabriel/H7XFVEzeDfqk"calls_hub_apiwith path/api/mists/H7XFVEzeDfqk(not/api/gabriel/mists/…). Mock_hub_apiand assert theapi_pathargument.MR_04— Unit test:run_readwith bare"H7XFVEzeDfqk"calls_hub_apiwith path/api/mists/H7XFVEzeDfqk. Existing happy-path smoke, now with explicit path assertion.MR_05— Unit test:run_readwith"owner/ID"does NOT include the owner in the path — theownerportion is silently discarded (it is advisory information only; the ID alone uniquely identifies a mist).MR_06— Unit test: when_hub_apireceives a 404,run_readexits with a message containing the HTTP status code (validates MR_02 fix).
Phase 4 — Staging smoke
MR_07—muse mist read gabriel/H7XFVEzeDfqk --hub https://staging.musehub.ai --jsonreturns the mist JSON withmist_id == "H7XFVEzeDfqk".MR_08—muse mist read H7XFVEzeDfqk --hub https://staging.musehub.ai --jsonreturns identical output (both forms are equivalent).
Acceptance criteria
muse mist read owner/IDandmuse mist read IDreturn identical JSON output.- HTTP 404 from the server surfaces as
❌ Hub returned HTTP 404: …— not a JSON parse error. - MR_03–MR_06 tests green.
- Staging smoke passes (MR_07–MR_08).
Out of scope
- Validating that the owner in
owner/IDmatches the mist's actual owner (the server owns that check; the CLI's job is just to extract the ID) - Changing the server-side routes
- Other mist subcommands — all others already handle
owner/IDcorrectly
Fixed on
dev(sha256:96c357b8), both phases from the plan.Phase 1:
run_readnow builds/api/mists/{id}for both bare-ID andowner/IDinput — the owner segment is discarded, matching every other mist subcommand.Phase 2:
_hub_api's 404 branch now reads❌ Hub returned HTTP 404: {detail}, consistent with every other status branch, so a 404 with a valid JSON body is never confused with a JSON-parse failure.Phase 3: 5 new tests in
tests/test_mist_read_api_path.pycovering MR_02–MR_06 (owner/ID uses correct path, bare-ID unchanged, owner discarded not embedded, both forms produce identical output, 404 surfaces HTTP status). All 92 existingtest_mist_cli.pytests still pass.Phase 4 (staging smoke, MR_07/MR_08) is left for you to verify against a live mist, since it needs a real staging hub round-trip outside this session's scope.