Remove allowUnknownExtensionConfig option from frontend app APIs

The `allowUnknownExtensionConfig` option was unused in practice — unknown
extension config was always reported via the error collector regardless of
the flag. For `createSpecializedApp`, unknown extension config is now always
included in the returned errors. For `createApp`, it is handled as a
console warning via `maybeCreateErrorPage`.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
This commit is contained in:
Patrik Oldsberg
2026-03-05 10:32:08 +01:00
parent d0b53e39fd
commit 92af1ae9c0
7 changed files with 19 additions and 26 deletions
@@ -0,0 +1,5 @@
---
'@backstage/frontend-app-api': minor
---
**BREAKING**: Removed the `allowUnknownExtensionConfig` option from `createSpecializedApp`. Unknown extension configuration is now always reported as an `INVALID_EXTENSION_CONFIG_KEY` error in the returned `errors` array instead.
@@ -0,0 +1,5 @@
---
'@backstage/frontend-defaults': minor
---
**BREAKING**: Removed the `allowUnknownExtensionConfig` option from `createApp`. Unknown extension configuration now always produces a console warning instead.
-1
View File
@@ -169,7 +169,6 @@ export type CreateSpecializedAppOptions = {
bindRoutes?(context: { bind: CreateAppRouteBinder }): void;
advanced?: {
apis?: ApiHolder;
allowUnknownExtensionConfig?: boolean;
extensionFactoryMiddleware?:
| ExtensionFactoryMiddleware
| ExtensionFactoryMiddleware[];
@@ -255,17 +255,6 @@ export type CreateSpecializedAppOptions = {
*/
apis?: ApiHolder;
/**
* If set to true, the system will silently accept and move on if
* encountering config for extensions that do not exist. The default is to
* reject such config to help catch simple mistakes.
*
* This flag can be useful in some scenarios where you have a dynamic set of
* extensions enabled at different times, but also increases the risk of
* accidentally missing e.g. simple typos in your config.
*/
allowUnknownExtensionConfig?: boolean;
/**
* Applies one or more middleware on every extension, as they are added to
* the application.
-1
View File
@@ -23,7 +23,6 @@ export function createApp(options?: CreateAppOptions): {
// @public
export interface CreateAppOptions {
advanced?: {
allowUnknownExtensionConfig?: boolean;
configLoader?: () => Promise<{
config: ConfigApi;
}>;
@@ -283,7 +283,9 @@ describe('createApp', () => {
).resolves.toBeInTheDocument();
});
it('should allow unknown extension config if the flag is set', async () => {
it('should warn about unknown extension config', async () => {
const warnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
const app = createApp({
features: [
appPlugin,
@@ -300,7 +302,6 @@ describe('createApp', () => {
}),
],
advanced: {
allowUnknownExtensionConfig: true,
configLoader: async () => ({
config: mockApis.config({
data: {
@@ -316,6 +317,12 @@ describe('createApp', () => {
await renderWithEffects(app.createRoot());
await expect(screen.findByText('Derp')).resolves.toBeInTheDocument();
expect(warnSpy).toHaveBeenCalledWith('App startup encountered warnings:');
expect(warnSpy).toHaveBeenCalledWith(
'INVALID_EXTENSION_CONFIG_KEY: Extension unknown:lols/wut does not exist',
);
warnSpy.mockRestore();
});
it('should make the app structure available through the AppTreeApi', async () => {
let appTreeApi: AppTreeApi | undefined = undefined;
@@ -58,17 +58,6 @@ export interface CreateAppOptions {
* Advanced, more rarely used options.
*/
advanced?: {
/**
* If set to true, the system will silently accept and move on if
* encountering config for extensions that do not exist. The default is to
* reject such config to help catch simple mistakes.
*
* This flag can be useful in some scenarios where you have a dynamic set of
* extensions enabled at different times, but also increases the risk of
* accidentally missing e.g. simple typos in your config.
*/
allowUnknownExtensionConfig?: boolean;
/**
* Sets a custom config loader, replacing the builtin one.
*