Skip to content

[13.3] aspire config set still writes booleans as JSON strings (write-path fix from PR #15638 didn't ship) #16692

@IEvangelist

Description

@IEvangelist

Description

In Aspire CLI 13.3.0, aspire config set <key> <value> still writes boolean values as JSON strings ("true" / "false"), even though the 13.3 changelog (wiki) and PR #15638's body explicitly advertise the write path as fixed:

🐛 Fix config boolean handling: crash on read, wrong types on write — PR #15638

Fix the write path to emit correct JSON types … ConfigurationService.SetNestedValue wrote all values as JSON strings (e.g., "true" instead of true) … Fixed SetNestedValue to write proper JSON types — added ConvertToTypedJsonValue so booleans are written as true/false, integers as numbers, and only non-parseable values remain as strings.

What actually shipped in d6f5fe3bf (the merge commit for #15638 on main and release/13.3) only adds the read side (FlexibleBooleanConverter) — the write path was never modified. ConfigurationService.SetNestedValue is unchanged and still assigns the raw string value directly to a JsonObject indexer:

// src/Aspire.Cli/Configuration/ConfigurationService.cs ~line 206
private static void SetNestedValue(JsonObject settings, string key, string value)
{
    ...
    var finalKey = keyParts[keyParts.Length - 1];
    currentObject[finalKey] = value;   // <-- always wraps as JsonValue<string>
}

There is no ConvertToTypedJsonValue method anywhere in main, release/13.3, or the merge commit (git log -S "ConvertToTypedJsonValue" returns no matches).

The result: every existing aspire.config.json written by 13.3 has incorrectly-typed booleans. This is even visible in maintainer diagnostics — see #16601 where ~/.aspire/aspire.config.json shows "stagingChannelEnabled": "true" (string).

Repro

mkdir bool-repro; cd bool-repro
aspire config set features.stagingChannelEnabled true       --non-interactive --nologo
aspire config set features.experimentalPolyglot:java true   --non-interactive --nologo
type aspire.config.json

Expected

{
  "features": {
    "stagingChannelEnabled": true,
    "experimentalPolyglot": { "java": true }
  }
}

Actual (13.3.0 on Windows; also reproduced on the bundled CLI elsewhere)

{
  "features": {
    "stagingChannelEnabled": "true",
    "experimentalPolyglot": { "java": "true" }
  }
}

Both top-level (features.stagingChannelEnabled) and colon-nested (features.experimentalPolyglot:java) writes produce JSON strings.

aspire config get features.stagingChannelEnabled does return true (the read-side FlexibleBooleanConverter from #15638 hides this), so the read no longer crashes — but the file on disk is still wrong, and aspire doctor flags the resulting nested object as an invalid boolean.

Why this matters

  1. The behavior contradicts both the merged PR description and the public 13.3 changelog, which advertise the write-path fix as shipped.
  2. Any new tooling or future readers that don't go through FlexibleBooleanConverter (e.g., JsonSerializer.Deserialize<bool>, IConfiguration with strict typing, third-party tools) will fail or misbehave on values written by 13.3.
  3. Existing users who run aspire config set accumulate string-typed booleans; rolling forward a stricter reader becomes a breaking change.

Suggested fix

Land the write-side change that the PR body originally described:

  • In ConfigurationService.SetNestedValue, parse the incoming string value into a typed JsonValue (bool, int/long, double, otherwise string) before assigning to the JsonObject — i.e., the ConvertToTypedJsonValue helper described in [main] Fix config boolean handling: crash on read, wrong types on write #15638.
  • Mirror it in ConfigurationHelper.TryNormalizeSettingsFile for the colon-key normalization path (the existing JsonNode.DeepClone() change preserves type for already-typed JSON, but does not type-promote the freshly written string from set).
  • Add an aspire config set test that asserts the on-disk JSON for both set features.foo true and set features.foo:bar true.

Environment

Aspire CLI: 13.3.0+37f41c00d5267bb1a4238187b15e112a14ee6372
OS: Windows 11 / Windows_NT
Channel: staging

References

Found while running a Ralph-style validation of every entry in the 13.3 changelog.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions