---
title: "ADR-034: Remove the ExtensionConfiguration default-provider fallback"
manual: "TYPO3 LLM Extension"
version: "0.35"
permalink: "https://docs.typo3.org/permalink/netresearch/nr-llm:adr-034@0.35"
source: "Adr/Adr034RemoveExtensionConfigDefaultProvider.rst"
modified: "2026-09-16T22:09:16+00:00"
---

# ADR-034: Remove the ExtensionConfiguration default-provider fallback

-   *Status:* Accepted
-   *Date:* 2026-06-24
-   *Authors:* Netresearch DTT GmbH

## Context

`LlmServiceManager` carried a session-level *default provider*: a
nullable `defaultProvider` string seeded from
`ExtensionConfiguration['nr_llm']['defaultProvider']` and mutable at
runtime through `setDefaultProvider()` / `getDefaultProvider()`
(both on the public `LlmServiceManagerInterface`). When a generic
`chat()` / `complete()` / `streamChat()` call pinned no
provider, `getProvider(null)` fell back to that string.

This is a remnant of the original provider-centric design that predates
the database-backed three-tier model ([ADR-013: Three-level configuration architecture (Provider-Model-Configuration)](https://docs.typo3.org/permalink/netresearch/nr-llm:adr-013@0.35),
[ADR-001: Provider Abstraction Layer](https://docs.typo3.org/permalink/netresearch/nr-llm:adr-001@0.35)). Since [ADR-021: Provider Fallback Chain](https://docs.typo3.org/permalink/netresearch/nr-llm:adr-021@0.35) / [ADR-026: Provider Middleware Pipeline](https://docs.typo3.org/permalink/netresearch/nr-llm:adr-026@0.35), the generic
entry points resolve the **active default** `tx_nrllm_configuration`
record first (`isActive = 1 AND isDefault = 1`, via
`LlmConfigurationRepository::findDefault()`); the
`ExtensionConfiguration` fallback was only ever reached when no such
record existed.

In practice the fallback was inert: the `defaultProvider` key was
never exposed in `ext_conf_template.txt`, so it was always `null` in
production unless an integrator set it by hand in `additional.php`. It
was also misleading — together with the orphaned `plugin.tx_nrllm`
TypoScript (removed in [#255](https://github.com/netresearch/t3x-nr-llm/pull/255), answering
[discussion #254](https://github.com/netresearch/t3x-nr-llm/discussions/254)) it
suggested a second, config-driven way to choose a provider that no code
path honoured as the source of truth.

## Decision

Remove the default-provider concept from `LlmServiceManager`
entirely. The database is the single source of truth for provider
selection.

1.  **Drop the state and its seed.** The `defaultProvider` property and
    the `ExtensionConfiguration['nr_llm']['defaultProvider']` read in
    `loadConfiguration()` are removed. The rest of the extension
    configuration (provider-specific settings consumed by
    `registerProvider()`) is unaffected.
1.  **Remove the public accessors.** `setDefaultProvider()` and
    `getDefaultProvider()` are removed from
    `LlmServiceManagerInterface` and its implementation. **This is a
    breaking change** to the public service contract.
1.  **\`getProvider(null)\` throws.** With no fallback,
    `getProvider()` requires an explicit identifier; called with
    `null` it throws `ProviderException` (code `4867297358`)
    with guidance to configure a default Configuration in the backend
    module. The signature keeps the nullable parameter for callers that
    pass a possibly-null pinned provider.

## Consequences

-   ● One way to choose a provider: pin it per call (the `provider`
    option on `ChatOptions` / `EmbeddingOptions`) or let the
    generic path resolve the active default Configuration. No silent,
    inert third path.
-   ● The `LlmServiceManagerInterface` shrinks by two methods that
    no production code consumed.
-   ◐ **Breaking:** integrators that called
    `setDefaultProvider()` / `getDefaultProvider()`, or relied
    on the `defaultProvider` extension-config key, must instead create
    an active+default Configuration record or pin the provider per call.
    No production deployment used the key (it was never exposed in
    `ext_conf_template.txt`), so real-world impact is expected to be
    nil.
-   ● No production behaviour change in practice: the generic entry
    points already resolved the database default first, and the fallback
    was never populated in production.
-   ◐ Supersedes the provider-default resolution steps of [ADR-007: Multi-Provider Strategy](https://docs.typo3.org/permalink/netresearch/nr-llm:adr-007@0.35)
    ("Default provider from configuration" / "First configured provider by
    priority"): provider selection is now per-call or via the active default
    Configuration only, with no extension-config or priority fallback.
