Skip to content

CLI config discovery doesn't find aspire.config.json adjacent to AppHost in subdirectory #15402

@joperezr

Description

@joperezr

Summary

When running aspire run (or aspire restore) from a parent directory of the AppHost, the CLI fails to discover an existing aspire.config.json that lives next to the AppHost file in a subdirectory. Instead, it creates a new incomplete aspire.config.json at the CWD, which then causes the AppHost server to fail.

Root Cause

There is an asymmetry in how the CLI discovers the AppHost file vs. the config file:

  • AppHost discovery (ProjectLocator): Scans downward into subdirectories from CWD → successfully finds src/apphost.ts
  • Config discovery (ConfigurationService.FindNearestSettingsFile()): Searches upward from CWD → never finds src/aspire.config.json

When the config isn't found, GetOrCreateLocalAspireConfigFile() (ProjectLocator.cs L448) creates a new aspire.config.json at CWD:

// ProjectLocator.cs, line 448
var newConfigPath = Path.Combine(executionContext.WorkingDirectory.FullName, AspireConfigFile.FileName);

This new config only has appHost.path set (e.g. "src/apphost.ts") but is missing all the user's packages, profiles, channel, and other settings — causing the AppHost server to fail.

Meanwhile, ConfigurationService.FindNearestSettingsFile() (ConfigurationService.cs L93-125) only walks upward:

private string FindNearestSettingsFile()
{
    var searchDirectory = executionContext.WorkingDirectory;

    while (searchDirectory is not null)
    {
        var newSettingsPath = Path.Combine(searchDirectory.FullName, AspireConfigFile.FileName);
        if (File.Exists(newSettingsPath))
            return newSettingsPath;

        searchDirectory = searchDirectory.Parent;  // Only searches UP
    }

    // Falls back to CWD
    return Path.Combine(executionContext.WorkingDirectory.FullName, AspireConfigFile.FileName);
}

Reproduction

  1. Create a polyglot TypeScript AppHost in a subdirectory:

    my-repo/
    ├── src/
    │   ├── apphost.ts
    │   └── aspire.config.json   ← has packages, profiles, channel, etc.
    └── (no aspire.config.json at root)
    
  2. Run from the repo root:

    cd my-repo
    aspire run
  3. Expected: CLI finds src/apphost.ts and uses src/aspire.config.json alongside it.

  4. Actual:

    🔍 Finding apphosts...
    src\apphost.ts
    🗄  Created settings file at 'aspire.config.json'.        ← creates incomplete config at root
    ❌ Failed to run TypeScript (Node.js) AppHost: Failed to authenticate to the AppHost server.
    

Log output confirming the issue

[INFO] [ConfigurationService] Found settings file at C:\Users\...\my-repo\aspire.config.json
[INFO] [GuestAppHostProject] Loaded config from C:\Users\...\my-repo (file exists: True)
[FAIL] [GuestAppHostProject] Failed to run TypeScript (Node.js) AppHost
System.InvalidOperationException: Failed to authenticate to the AppHost server.

The log shows it found/created the config at the repo root rather than using the existing one in src/.

Suggested fix

When the CLI discovers an AppHost file via subdirectory scanning, it should also check for aspire.config.json in the AppHost's directory (and its parent chain up to CWD) before falling back to creating a new one at CWD.

Possible approaches:

  1. After discovering the AppHost at src/apphost.ts, check src/aspire.config.json first
  2. Make FindNearestSettingsFile() accept an optional anchor directory (the AppHost's directory) instead of always starting from CWD
  3. In CreateSettingsFileAsync, if a config already exists adjacent to the discovered AppHost, use that instead of creating a new one

Workaround

Run aspire run from the directory containing both apphost.ts and aspire.config.json:

cd src
aspire run

Metadata

Metadata

Assignees

Labels

Type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions