spring-projects / spring-projects/spring-ai
OpenAI auto-config startup fails when only a sub-prefix credential is set
@sdeleuze is already working on this.
Since May 22, 2026.
- Dominant language
- Java
- Stars
- 9.5k
- Forks
- 2.9k
- Avg merge
- 1d 7h
- Merged PRs (30d)
- 6
Description
Background
While digging into #1818 (spring.ai.openai.image.api-key alone fails the context), I traced the failure to how OpenAI auto-configuration gates its model beans, not to anything image-specific. The same shape of bug applies to chat, embedding, audio.speech, audio.transcription, and moderation — image is just the first one that surfaced because that's the path the
original reporter took.
I'm filing this as a separate issue (with a follow-up PR) because the fix touches all six sub-configurations and introduces a small new Condition, which feels closer to a refactor than a single-bean bug fix. The change closes #1818 as a consequence. Happy to fold it back into #1818 if you'd prefer that flow.
Reproduction
# application.yml — startup fails with only this set
spring:
ai:
openai:
image:
api-key: sk-xxx
java.lang.IllegalStateException: At least one credential source must be specified:
credential (apiKey), workloadIdentity, or adminApiKey
at com.openai.core.ClientOptions$Builder.effectiveCredential(ClientOptions.kt:503)
... (wrapped by Spring as BeanCreationException during context startup)
Substitute chat, embedding, audio.speech, audio.transcription, or moderation for image above and the failure is identical — only the failing sub-configuration changes. Programmatic credentials, the OPENAI_API_KEY env var, and Microsoft Foundry passwordless setups exhibit the same shape: one valid credential source, five other
sub-configurations still try to register and fail fast.
Current behavior
The six OpenAI auto-configurations gate registration only on spring.ai.openai.api-key (the common prefix), even though Spring AI already accepts several other valid credential sources at the SDK level:
spring.ai.openai.<chat|image|embedding|audio.speech|audio.transcription|moderation>.api-key- a programmatic
Credentialset onOpenAiCommonPropertiesor any of the sub-*Properties OPENAI_API_KEYenv var (default OpenAI endpoint)- Microsoft Foundry endpoints, where the api-key may legitimately be absent because passwordless auth is used. Detected by any of:
spring.ai.openai.microsoft-foundry=truebase-urlending inopenai.azure.comorcognitiveservices.azure.commicrosoft-deployment-name,deployment-name, ormicrosoft-foundry-service-versionset
In all of these cases, all six @Configuration classes still register; OpenAiSetup then fails fast on the sub-configurations that have no usable credential, and the failure takes the whole application context down before the working sub-configuration ever boots.
Why a custom Condition
The first thing I tried was widening the existing @ConditionalOnProperty — the same shape that's been attempted before:
@ConditionalOnProperty(
prefix = "spring.ai.openai",
name = { "api-key", "image.api-key" },
matchIfMissing = false
)
That doesn't work: Spring Boot's name = {a, b} semantics is AND, not OR — it matches only when both keys are set, which is the opposite of what we need. The condition needs OR-of-credential-sources logic, which I don't see a way to express declaratively without a custom SpringBootCondition.
Proposed change
A single OpenAiConnectionCondition utility with one inner condition per sub-configuration (Chat, Image, Embedding, AudioSpeech, AudioTranscription, Moderation). Each one independently checks the credential sources listed above with short-circuit OR semantics. If none match, the corresponding @Bean does not register, and the rest of the context boots normally.
The conditions sit on the @Bean method, not the @Configuration class, so:
@EnableConfigurationProperties(OpenAi*Properties)still runs — the properties bean stays available for other code that injects it.- The existing model-selector
@ConditionalOnProperty(spring.ai.model.<kind>)keeps working unchanged.
A working branch with this change and 13 tests covering each credential source per sub-configuration is ready (all green on the spring-ai-autoconfigure-model-openai module). I'll open the PR right after this issue if the direction looks reasonable.
Scope / non-goals
- No public API changes, no new dependencies.
- No behavior change for users who already set
spring.ai.openai.api-key— that branch matches first, exactly as today. - Closes #1818 as a side effect.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.