`canister settings show --json` serializes numeric settings as Nat limb arrays (and disagrees with `canister status --json`)
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 115
- Forks
- 12
- Avg merge
- 2d 19h
- Merged PRs (30d)
- 36
Description
Summary
icp canister settings show --json serializes the Candid DefiniteCanisterSettings struct directly, so every numeric setting comes out as an array of the Nat's internal limbs rather than a number. A 4 GiB memory_allocation renders as [0,1].
The same shortcut also makes the two commands that report canister settings disagree on how they render the visibility settings, for the same underlying value.
Repro
$ icp canister settings show my-canister --json
{"controllers":[...],"compute_allocation":[5],"memory_allocation":[0,1],"freezing_threshold":[2592000],
"reserved_cycles_limit":[],"log_visibility":"public","log_memory_limit":[],"status_visibility":"controllers",...}
For a canister with compute_allocation: 5, memory_allocation: 4gib, freezing_threshold: 30d:
| Field | Actual | Expected |
|---|---|---|
compute_allocation (5) |
[5] |
5 or "5" |
memory_allocation (4 GiB) |
[0,1] |
4294967296 or "4294967296" |
freezing_threshold (30d) |
[2592000] |
2592000 or "2592000" |
| any zero value | [] |
0 or "0" |
[0,1] for 4 GiB is not just awkward, it is wrong in a way a consumer cannot recover from without knowing the limb encoding.
Root cause
candid::Nat's Serialize impl targets Candid, not JSON, and exposes the underlying BigUint representation. settings/show.rs does:
serde_json::to_string(&result.settings)
icp canister status --json does not have this problem: it maps the reply into a local SerializableCanisterSettings that converts each Nat with .to_string().
Secondary symptom: the two commands disagree
Because status maps through its own type and settings show does not, the same setting renders two ways:
canister status --json |
canister settings show --json |
|
|---|---|---|
log_visibility = controllers |
{"type":"Controllers"} |
"controllers" |
| allowed viewers | {"type":"AllowedViewers","value":["aaaaa-aa"]} |
{"allowed_viewers":["aaaaa-aa"]} |
compute_allocation = 5 |
"5" |
[5] |
Why this looks accidental rather than deliberate
- The bespoke JSON mapping for
canister statusarrived in #225, which builtSerializableCanisterStatusResultspecifically to stringify theNatfields. canister settings showgained--jsonlater, in #499, whose stated goal was "only output settings" and erroring for non-controllers. It stopped delegating tocanister statusand serialized the Candid type directly. Nothing in that PR's description, the code, or the changelog mentions the output shape changing or the two commands diverging.- No test asserts the values in
settings show --json; the existing assertion only checks that the field names are present, which is why[0,1]went unnoticed.
Suggested fix
Reuse one serializable representation for both commands. canister status's SerializableCanisterSettings already exists and handles the Nat conversion; lifting it somewhere both commands can use would fix the numbers and make the two agree.
Worth deciding deliberately whether the shared shape keeps status's tagged {"type","value"} visibility form or the Candid-style one, since aligning them is a breaking output change for whichever command moves.
Note
Found while working on #727 (adding status_visibility), which had to add a status_visibility key to both paths and surfaced the divergence. That PR deliberately does not change either shape.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in crates/icp-cli/src/commands/canister/settings/show.rs and compare its JSON serialization with canister status's SerializableCanisterSettings mapping. Trace the existing settings show JSON assertion and the status representation, then decide and document the shared output shape, including visibility fields. Done means numeric settings serialize as recoverable values and both commands agree.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- cli
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100