You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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:
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
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
The behavior contradicts both the merged PR description and the public 13.3 changelog, which advertise the write-path fix as shipped.
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.
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:
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
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:What actually shipped in
d6f5fe3bf(the merge commit for #15638 onmainandrelease/13.3) only adds the read side (FlexibleBooleanConverter) — the write path was never modified.ConfigurationService.SetNestedValueis unchanged and still assigns the rawstring valuedirectly to aJsonObjectindexer:There is no
ConvertToTypedJsonValuemethod anywhere inmain,release/13.3, or the merge commit (git log -S "ConvertToTypedJsonValue"returns no matches).The result: every existing
aspire.config.jsonwritten by 13.3 has incorrectly-typed booleans. This is even visible in maintainer diagnostics — see #16601 where~/.aspire/aspire.config.jsonshows"stagingChannelEnabled": "true"(string).Repro
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.stagingChannelEnableddoes returntrue(the read-sideFlexibleBooleanConverterfrom #15638 hides this), so the read no longer crashes — but the file on disk is still wrong, andaspire doctorflags the resulting nested object as an invalid boolean.Why this matters
FlexibleBooleanConverter(e.g.,JsonSerializer.Deserialize<bool>,IConfigurationwith strict typing, third-party tools) will fail or misbehave on values written by 13.3.aspire config setaccumulate 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:
ConfigurationService.SetNestedValue, parse the incomingstring valueinto a typedJsonValue(bool,int/long,double, otherwisestring) before assigning to theJsonObject— i.e., theConvertToTypedJsonValuehelper described in [main] Fix config boolean handling: crash on read, wrong types on write #15638.ConfigurationHelper.TryNormalizeSettingsFilefor the colon-key normalization path (the existingJsonNode.DeepClone()change preserves type for already-typed JSON, but does not type-promote the freshly written string fromset).aspire config settest that asserts the on-disk JSON for bothset features.foo trueandset features.foo:bar true.Environment
References
NOT_PLANNED; comments include"stagingChannelEnabled": "true"showing the same string-write bug in maintainer configsrc/Aspire.Cli/Configuration/ConfigurationService.cs(SetNestedValue, ~line 206)Found while running a Ralph-style validation of every entry in the 13.3 changelog.