microsoft / microsoft/aspire

[bug] aspire run crashes with 'Null character in path' when aspire.config.json records an invalid appHost.path (#17624 missed CreateSettingsFileAsync)

Open
#19,137 2 comments 0 reactions 0 assignees View on GitHub
area-cli
Dominant language
C#
Stars
6.3k
Forks
991
Avg merge
2d 15h
Merged PRs (30d)
196

Description

`aspire run` crashes with `Null character in path` when `aspire.config.json` records an invalid `appHost.path`. #17624 fixed this for the read path, but the write path in `ProjectLocator.CreateSettingsFileAsync` resolves the same value without the guard that fix added.

### Repro

Two AppHosts in a workspace, and an `aspire.config.json` whose `appHost.path` contains a NUL byte (legal in JSON, so it survives parsing):

```json
{"appHost":{"path":"First\u0000AppHost.csproj"}}
```

```console
$ aspire run --apphost SecondAppHost/SecondAppHost.csproj
❌ An unexpected error occurred: Null character in path. (Parameter 'path')
```

Reproduced on `main` (`a50e553a8c`) with a locally built CLI. No environment variables set. Any character in `Path.GetInvalidPathChars()` should behave the same.

### Cause

The canonical readers validate before resolving. `GetAppHostProjectFileFromSettingsAsync` calls `IsValidConfiguredAppHostPath` first (`ProjectLocator.cs:658` and `:715`), which rejects `'\0'` and `Path.GetInvalidPathChars()` precisely because `Path.Combine` / `Path.GetFullPath` throw `ArgumentException` on them. The comment at `ProjectLocator.cs:653-657` cites #17624.

The upward config search in `CreateSettingsFileAsync` resolves the recorded path with no such guard:

```csharp
var resolvedPath = Path.GetFullPath(
Path.IsPathRooted(existingPath) ? existingPath : Path.Combine(configDir, existingPath));
```

`ProjectLocator.cs:1124-1125` (line numbers as of `60e8e122f2`). The `ArgumentException` escapes as a generic "An unexpected error occurred", which is the same symptom #17624 was filed for.

An explicit `--apphost` never runs the settings reader, so nothing validates the recorded string before this point.

### Why this needs a design decision, not just a guard

`IsValidConfiguredAppHostPath` takes a `silent` flag and either displays an error or logs a warning. `CreateSettingsFileAsync` has no such flag, and it is a write path, so fixing it means deciding what should happen when a *write* encounters a malformed recorded value — fail, warn and overwrite, or silently overwrite. That choice is user-visible and deserves its own tests.

### Notes

Found while working on #19080 (PR #19126). That PR does not touch this code path and adds no new unguarded resolution; it is flagged there so the crash is not misread as a regression. Filing separately because #17624 already missed this spot once, and a PR description stops being discoverable after merge.

Contributor guide

Open the contributing guide

Research direction

Start in ProjectLocator.cs at IsValidConfiguredAppHostPath, GetAppHostProjectFileFromSettingsAsync, and CreateSettingsFileAsync around the cited lines. Reproduce the command with a NUL-containing appHost.path, then determine the intended write-path behavior—fail, warn and overwrite, or silently overwrite. Add tests covering the chosen behavior and confirm aspire run no longer crashes generically.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
cli
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.