If you set spring.profiles.active to a value that contains a * the app will fail to start.

Steps to reproduce

Spring Boot 3.0.2 simplest application from start.spring.io:

@SpringBootApplication
public class WackyProfileApplication {
    public static void main(String[] args) {
        SpringApplication.run(WackyProfileApplication.class, args);
    }
}

Start it w/ spring.profiles.active set to foo*bar via any normal means such as: - sysprop - envvar - property in application.yml - profile property in maven/gradle plugin

App fails to start and reports the following in the log:

com.example.wackyprofile.WackyprofileApplication
23:14:37.244 [main] ERROR org.springframework.boot.SpringApplication - Application run failed
java.lang.IllegalStateException: Location 'file:./application-foo*bar.yaml' must end with '*/'
    at org.springframework.util.Assert.state(Assert.java:97)
    at org.springframework.boot.context.config.LocationResourceLoader.validatePattern(LocationResourceLoader.java:134)
    at org.springframework.boot.context.config.LocationResourceLoader.getResources(LocationResourceLoader.java:95)
    at org.springframework.boot.context.config.StandardConfigDataLocationResolver.resolvePattern(StandardConfigDataLocationResolver.java:313)
    at org.springframework.boot.context.config.StandardConfigDataLocationResolver.resolve(StandardConfigDataLocationResolver.java:299)
    at org.springframework.boot.context.config.StandardConfigDataLocationResolver.resolve(StandardConfigDataLocationResolver.java:251)
    at org.springframework.boot.context.config.StandardConfigDataLocationResolver.resolveProfileSpecific(StandardConfigDataLocationResolver.java:150)
    at org.springframework.boot.context.config.ConfigDataLocationResolvers.lambda$resolve$2(ConfigDataLocationResolvers.java:107)
    at org.springframework.boot.context.config.ConfigDataLocationResolvers.resolve(ConfigDataLocationResolvers.java:113)
    at org.springframework.boot.context.config.ConfigDataLocationResolvers.resolve(ConfigDataLocationResolvers.java:106)
    at org.springframework.boot.context.config.ConfigDataLocationResolvers.resolve(ConfigDataLocationResolvers.java:94)
    at org.springframework.boot.context.config.ConfigDataImporter.resolve(ConfigDataImporter.java:105)
    at org.springframework.boot.context.config.ConfigDataImporter.resolve(ConfigDataImporter.java:97)
    at org.springframework.boot.context.config.ConfigDataImporter.resolveAndLoad(ConfigDataImporter.java:85)
    at org.springframework.boot.context.config.ConfigDataEnvironmentContributors.withProcessedImports(ConfigDataEnvironmentContributors.java:115)
    at org.springframework.boot.context.config.ConfigDataEnvironment.processWithProfiles(ConfigDataEnvironment.java:313)
    at org.springframework.boot.context.config.ConfigDataEnvironment.processAndApply(ConfigDataEnvironment.java:234)
    at org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor.postProcessEnvironment(ConfigDataEnvironmentPostProcessor.java:96)
    at org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor.postProcessEnvironment(ConfigDataEnvironmentPostProcessor.java:89)
    at org.springframework.boot.env.EnvironmentPostProcessorApplicationListener.onApplicationEnvironmentPreparedEvent(EnvironmentPostProcessorApplicationListener.java:109)

Cause

The * qualifies it to be processed as a pattern in StandardConfigDataLocationResolver#resolve(StandardConfigDataReference)

Comment From: onobc

This is an edge-casey situation and arguably a terrible choice to include a wildcard in your profile name. However, there is no place in the Spring Boot nor Spring Framework docs (that I could find) that guide the user to the rules for a profile name. Maybe just adding a small section to the docs would suffice.

Comment From: onobc

Another interesting point, there is a validateProfile in Environment whose only requirement is that the profile has text and does not begin w a !. Different consumers of the profile probably have different validation requirements than others.

Comment From: philwebb

I think we should tighten the rules for Spring Boot applications. The application-<profile> file is one example of something that will break but I suspect there are others. For example , will probably break the list parsing and !, &, | will break Profiles.of.

Comment From: wilkinsona

We've had an issue related to , in the past: https://github.com/spring-projects/spring-boot/issues/19537

Comment From: bbulgarelli

I started working on this issue and I added the following code in the beginning of SpringBootContextLoader.setActiveProfiles:

private void setActiveProfiles(ConfigurableEnvironment environment, String[] profiles, boolean applicationEnvironment){
    ***
    for (String profile : profiles) {
        if (containsProhibitedCharacters(profile)) {
            throw new IllegalArgumentException("Invalid profile: '" + profile + "'. Profile names can't contain '*', '&', '!' or '|'.");
        }
    }
    ***
}

And I also created the following method:

private boolean containsProhibitedCharacters(String str){
    String regex = ".*[*&!|].*";
    return str.matches(regex);
}

I didn't include , in the regex expression, because it would break the following unit test that already exists:

@Test
void activeProfileWithComma() {
    assertThat(getActiveProfiles(ActiveProfileWithComma.class)).containsExactly("profile1,2");
}

I would like to know if the changes I made solve the issue correctly. If they do, what should I do about the comma problem?

P.s.: I also made the unit tests that verify the changes I made.

Comment From: philwebb

Thanks for looking at this @bbulgarelli. Looking at commit https://github.com/spring-projects/spring-boot/commit/7ab2bca3766a8e5c67b4ffbbc7e019b391f29e2d it seems like we added the profile test when fixing #19537. I think we added the comma test for completeness, but I think it's fine to remove it. A better exception would have actually helped the reporter of #19537.

Feel free to submit a pull-request if you have something you'd like us to review.

Comment From: mhalbritter

Superseded by #43176.