dfinity / dfinity/icp-cli

`canister settings show --json` serializes numeric settings as Nat limb arrays (and disagrees with `canister status --json`)

Open
#728 0 comments 0 reactions 0 assignees View on GitHub

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 status arrived in #225, which built SerializableCanisterStatusResult specifically to stringify the Nat fields.
  • canister settings show gained --json later, in #499, whose stated goal was "only output settings" and erroring for non-controllers. It stopped delegating to canister status and 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.