Skip to content

AppHost fails to start unless all profiles are "correct" #8795

Open
@dluc

Description

@dluc

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

When running Aspire AppHost, the process validates all profiles in launchSettings.json, even the extra ones defined for custom dev tasks.

Given the following launchSettings.json

{
  "$schema": "https://json.schemastore.org/launchsettings.json",
  "profiles": {
    "http": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": false,
      "applicationUrl": "http://localhost:60000",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "https": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": false,
      "applicationUrl": "https://localhost:60001;http://localhost:60000",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "debug": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": false,
      "applicationUrl": "https://localhost:60001;http://localhost:60000",
      "environmentVariables": {
        "FOO": 123
      }
    }
  }
}

where the "debug" profile has a minor issue - "FOO" should be a string not a number - Aspire AppHost fails to start and throws an exception:

Unhandled exception. Aspire.Hosting.DistributedApplicationException: Failed to get effective launch profile for project resource 'MyProject'. There is malformed JSON in the project's launch settings file at 'MyProject/Properties/launchSettings.json'
---> System.Text.Json.JsonException: The JSON value could not be converted to System.String. Path: $.profiles.debug.environmentVariables.FOO | LineNumber: 27 | BytePositionInLine: 20.
---> System.InvalidOperationException: Cannot get the value of a token type 'Number' as a string.
at System.Text.Json.ThrowHelper.ThrowInvalidOperationException_ExpectedString(JsonTokenType tokenType)
at System.Text.Json.Utf8JsonReader.GetString()
at System.Text.Json.Serialization.Converters.StringConverter.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)
at System.Text.Json.Serialization.JsonConverter1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value, Boolean& isPopulatedValue) at System.Text.Json.Serialization.JsonDictionaryConverter3.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, TDictionary& value)
at System.Text.Json.Serialization.Converters.JsonMetadataServicesConverter1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value) at System.Text.Json.Serialization.JsonConverter1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value, Boolean& isPopulatedValue)
at System.Text.Json.Serialization.Metadata.JsonPropertyInfo1.ReadJsonAndSetMember(Object obj, ReadStack& state, Utf8JsonReader& reader) at System.Text.Json.Serialization.Converters.ObjectDefaultConverter1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
at System.Text.Json.Serialization.Converters.JsonMetadataServicesConverter1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value) at System.Text.Json.Serialization.JsonConverter1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value, Boolean& isPopulatedValue)
at System.Text.Json.Serialization.JsonDictionaryConverter3.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, TDictionary& value) at System.Text.Json.Serialization.Converters.JsonMetadataServicesConverter1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
at System.Text.Json.Serialization.JsonConverter1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value, Boolean& isPopulatedValue) at System.Text.Json.Serialization.Metadata.JsonPropertyInfo1.ReadJsonAndSetMember(Object obj, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.Serialization.Converters.ObjectDefaultConverter1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value) at System.Text.Json.Serialization.Converters.JsonMetadataServicesConverter1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
at System.Text.Json.Serialization.JsonConverter1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value, Boolean& isPopulatedValue) at System.Text.Json.Serialization.JsonConverter1.ReadCore(Utf8JsonReader& reader, T& value, JsonSerializerOptions options, ReadStack& state)
--- End of inner exception stack trace ---
at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& state, Utf8JsonReader& reader, Exception ex)
at System.Text.Json.Serialization.JsonConverter1.ReadCore(Utf8JsonReader& reader, T& value, JsonSerializerOptions options, ReadStack& state) at System.Text.Json.Serialization.Metadata.JsonTypeInfo1.ContinueDeserialize(ReadBufferState& bufferState, JsonReaderState& jsonReaderState, ReadStack& readStack, T& value)
at System.Text.Json.Serialization.Metadata.JsonTypeInfo1.Deserialize(Stream utf8Json) at System.Text.Json.JsonSerializer.Deserialize[TValue](Stream utf8Json, JsonTypeInfo1 jsonTypeInfo)
at Aspire.Hosting.LaunchProfileExtensions.GetLaunchSettings(IProjectMetadata projectMetadata, String resourceName) in //src/Shared/LaunchProfiles/LaunchProfileExtensions.cs:line 97
--- End of inner exception stack trace ---
at Aspire.Hosting.LaunchProfileExtensions.GetLaunchSettings(IProjectMetadata projectMetadata, String resourceName) in /
/src/Shared/LaunchProfiles/LaunchProfileExtensions.cs:line 103
at Aspire.Hosting.LaunchProfileExtensions.GetLaunchSettings(ProjectResource projectResource) in //src/Shared/LaunchProfiles/LaunchProfileExtensions.cs:line 28
at Aspire.Hosting.LaunchProfileExtensions.TrySelectLaunchProfileFromDefaultAnnotation(ProjectResource projectResource, String& launchProfileName) in /
/src/Shared/LaunchProfiles/LaunchProfileExtensions.cs:line 138
at Aspire.Hosting.LaunchProfileExtensions.SelectLaunchProfileName(ProjectResource projectResource) in //src/Shared/LaunchProfiles/LaunchProfileExtensions.cs:line 179
at Aspire.Hosting.LaunchProfileExtensions.GetEffectiveLaunchProfile(ProjectResource projectResource, Boolean throwIfNotFound) in /
/src/Shared/LaunchProfiles/LaunchProfileExtensions.cs:line 33
at Aspire.Hosting.ProjectResourceBuilderExtensions.WithProjectDefaults(IResourceBuilder1 builder, ProjectResourceOptions options) in /_/src/Aspire.Hosting/ProjectResourceBuilderExtensions.cs:line 341 at Aspire.Hosting.ProjectResourceBuilderExtensions.AddProject(IDistributedApplicationBuilder builder, String name, String projectPath, Action1 configure) in //src/Aspire.Hosting/ProjectResourceBuilderExtensions.cs:line 282
at Aspire.Hosting.ProjectResourceBuilderExtensions.AddProject(IDistributedApplicationBuilder builder, String name, String projectPath) in /
/src/Aspire.Hosting/ProjectResourceBuilderExtensions.cs:line 100

Expected Behavior

While the error is ok-ish, there is no reason to validate every profile in launchSettings.json, is there? It seems a waste of resources, and AppHost should just start if the profile selected is fine, ignoring other profiles.

Outside the scope of this issue: the env var parser could be improved, just taking the number as a string, like bash vars and .env files work.

Steps To Reproduce

Add a profile with an env var where the value is a number.

.NET Version info

.NET 9
Aspire 9.1

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-app-modelIssues pertaining to the APIs in Aspire.Hosting, e.g. DistributedApplication

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions