Skip to content

ProfilesParser silently accepts unbalanced parentheses in profile expressions #36540

@bebeis

Description

@bebeis

Profiles.of("dev)") or @Profile("dev)") with unbalanced parentheses is silently accepted and treated as "dev".

Reproduction

@RestController
@Profile("dev)") // unbalanced parentheses
public class DevController {

    @GetMapping("/message")
    public String readDevMessage() {
        return "spring";
    }
}
spring:
  application:
    name: profile
  profiles:
    active: dev
$ curl http://localhost:8080/message
spring
2026-03-26T19:26:50.425+09:00 DEBUG 97890 --- [profile] [           main] o.s.b.f.s.DefaultListableBeanFactory     : Creating shared instance of singleton bean 'devController'

The controller is loaded even though the profile expression is malformed.

Additional cases

The same behavior occurs with:

  • "dev)"
  • "(dev"

Both are accepted without any exception.

Observation

Unbalanced parentheses like "dev)" and "(dev" are accepted without any exception. They appear to be partially interpreted instead of being rejected.

From the implementation, it seems this behavior may be related to how ProfilesParser.parseTokens() handles closing parentheses at the top level, where unmatched ")" does not trigger a validation failure.

Question

Is this behavior intentional?

  • The current implementation already rejects standalone "(" or ")"
    • in ProfileTests.malformedExpressions()
  • However, when combined with profile names, unbalanced parentheses are silently accepted

So it is unclear whether:

  1. This is intended lenient parsing behavior, or
  2. This is a missing validation case

Additional note on tests

While reviewing existing tests, I noticed the following:

ProfilesTests.java 150:160

@Test
void ofAndExpression() {
    Profiles profiles = Profiles.of("(spring & framework)");
    assertAndExpression(profiles);
}

@Test
void ofAndExpressionWithoutSpaces() {
    Profiles profiles = Profiles.of("spring&framework)"); // here
    assertAndExpression(profiles);
}

Given the test name ofAndExpressionWithoutSpaces, I expected something like:

Profiles.of("(spring&framework)")

so I'm wondering if the current test is intentionally covering lenient parsing of unbalanced parentheses, or if this might be unintended.

Possible improvements

If this behavior is intentional, it might be helpful to clarify it in the documentation, as malformed expressions are currently accepted without any indication.

If not, it may be worth tightening validation in ProfilesParser to reject unbalanced parentheses consistently, and possibly updating related test cases as well.

I'd be happy to contribute a fix or improvements in either direction if this is something worth addressing.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions