docs/releases/v1.52.0-changelog.md
Upgrade Helper: https://backstage.github.io/upgrade-helper/?to=1.52.0
CatalogApi.queryEntities now accepts a totalItems option ('include' or 'exclude', default 'include') on initial requests. Pass 'exclude' to skip the totalItems count when the caller doesn't need it.devDependencies to dependencies. These were incorrectly demoted in #33936 because the source code only uses type imports, but the types still appear in the published API surface and need to be resolvable by consumers at build time.title field to connections, providing a human-readable display name for each connection. When not explicitly configured, the title defaults to the provider name (e.g. "GitHub") or includes the host when multiple connections share a type (e.g. "GitHub (ghe.acme.com)").fc4e624: Combobox now supports async collections, incremental loading, client and server search, and rich or custom item rendering. Loading placeholders expose .bui-ComboboxLoading and .bui-ComboboxLoadingRow, and stale visible results expose data-stale on .bui-ComboboxList.
BREAKING: The public ComboboxProps interface is now a union type.
Migration:
Required on upgrade:
Replace interfaces that extend ComboboxProps with type intersections.
- interface MyComboboxProps extends ComboboxProps {
- trackingId: string;
- }
+ type MyComboboxProps = ComboboxProps & {
+ trackingId: string;
+ };
Optional migration away from deprecated APIs:
Prefer id instead of value for plain options. Existing array-valued options using value remain supported as a deprecated compatibility path, but new option content fields and async option sources require id.
Move input state and custom filtering into the nested search configuration:
- <Combobox inputValue={query} onInputChange={setQuery} />
+ <Combobox search={{ inputValue: query, onInputChange: setQuery }} />
The existing top-level input state props remain supported as a deprecated compatibility path for plain-array options.
Affected components: Combobox
fc4e624: Select now supports async collections, incremental loading, client and server search, and rich or custom item rendering. Loading placeholders expose .bui-SelectLoading and .bui-SelectLoadingRow, and stale retained results expose data-stale on .bui-SelectList.
BREAKING: The public SelectProps interface is now a union type, and Select popover list content is no longer a direct child of .bui-SelectPopover.
Migration:
Required on upgrade:
Replace interfaces that extend SelectProps with type intersections.
- interface MySelectProps extends SelectProps {
- trackingId: string;
- }
+ type MySelectProps = SelectProps & {
+ trackingId: string;
+ };
Update CSS selectors that rely on list content being a direct child of .bui-SelectPopover. Select popovers now use the standard BUI Popover content structure, with contents wrapped in .bui-Box.bui-PopoverContent. The existing .bui-Popover.bui-SelectPopover root classes are unchanged.
Optional migration away from deprecated APIs:
Prefer id instead of value for plain options. Existing array-valued options using value remain supported as a deprecated compatibility path, but new option content fields and async option sources require id.
Replace searchable and searchPlaceholder with nested search configuration:
- <Select searchable searchPlaceholder="Search owners" />
+ <Select search={{ placeholder: 'Search owners' }} />
Affected components: Select
3d6c2e4: Updated the dark theme neutral background tokens to provide clearer contrast between neutral surfaces.
c86efcd: Fixed the Table component not filling its container width in Firefox. The overflow style is now applied to a wrapper element instead of the <table> element directly, which avoids a Firefox behavior where non-visible overflow on tables causes them to shrink-wrap to content size.
adf94f5: Make Skeleton component background aware, automatically adjusting its color to maintain visible contrast against neutral parent surfaces.
Affected components: Skeleton
b06b3c7: Fixed header tab links to respect the configured router basename.
Affected components: Header
14a101f: Switch now adapts its track and thumb colors based on the background context of its parent container, and uses the accent token family when selected.
Affected components: Switch
66c4e55: Fixed tab indicator not updating position when tab content changes width dynamically.
b33bb24: Added a new NumberField component for numeric input with support for min, max, step, and keyboard increment/decrement.
Affected components: NumberField
350407d: Fixed async pagination in Combobox and Select popovers so additional pages load as users scroll instead of loading every page immediately. Combobox now uses .bui-PopoverContent as its scroll container, while all Select variants use the new .bui-SelectResults results container.
Searchable Select keeps its search field fixed while results scroll. The new public classes .bui-SelectContent and .bui-SelectResults expose this layout for theme customization.
Affected components: Combobox, Select
e989f95: Fixed Combobox client search crashing when used with plain options.
Affected components: Combobox
1f709a3: Fixed Header breadcrumb typography so it remains consistent when component styles are loaded in different orders.
Affected components: Header
5d80f77: Introduces a new set of semantic color token families — Accent, Announcement, Warning, Negative, and Positive — each providing a consistent set of background, foreground, and border tokens for both light and dark themes. A gray scale (--bui-gray-1 through --bui-gray-11) and updated foreground tokens are also included.
The previous tokens remain in place for backward compatibility but are now deprecated and will be removed in a future release.
Migration:
Neutral backgrounds
The neutral background tokens keep their existing names (--bui-bg-app, --bui-bg-neutral-1 through --bui-bg-neutral-4) but are updated with new solid-color values for both light and dark themes. No token renaming is required. The -hover, -pressed, and -disabled interaction variants of these tokens are deprecated and should be removed.
Foreground
| Deprecated | Replacement |
|---|---|
--bui-fg-danger | --bui-fg-negative |
--bui-fg-success | --bui-fg-positive |
--bui-fg-info | --bui-fg-announcement |
Accent
| Deprecated | Replacement |
|---|---|
--bui-bg-solid | --bui-accent-bg |
--bui-bg-solid-hover | --bui-accent-bg-hover |
--bui-bg-solid-disabled | --bui-accent-bg-disabled |
--bui-fg-solid | --bui-accent-fg |
--bui-fg-solid-disabled | --bui-accent-fg-disabled |
Positive
| Deprecated | Replacement |
|---|---|
--bui-bg-success | --bui-positive-bg-subdued |
--bui-fg-success-on-bg | --bui-positive-fg-subdued |
--bui-border-success | --bui-positive-border |
Negative
| Deprecated | Replacement |
|---|---|
--bui-bg-danger | --bui-negative-bg-subdued |
--bui-fg-danger-on-bg | --bui-negative-fg-subdued |
--bui-border-danger | --bui-negative-border |
Warning
| Deprecated | Replacement |
|---|---|
--bui-bg-warning | --bui-warning-bg-subdued |
--bui-fg-warning-on-bg | --bui-warning-fg-subdued |
--bui-border-warning | --bui-warning-border |
Announcement
| Deprecated | Replacement |
|---|---|
--bui-bg-info | --bui-announcement-bg-subdued |
--bui-fg-info-on-bg | --bui-announcement-fg-subdued |
--bui-border-info | --bui-announcement-border |
FrontendHostDiscovery, which supports the discovery.endpoints configuration for per-plugin endpoint overrides. Note that this will start honoring discovery.endpoints (including string target values), so if you currently use internal-only targets there, update them to the object form and move the internal URL to target.internal, omitting target.external (or setting it to a browser-reachable URL) to avoid routing the frontend to internal URLs.8f20cc2: /entities/by-query now accepts a totalItems parameter ('include' or 'exclude', default 'include') that controls whether the response's totalItems count is computed. Pass 'exclude' to skip the count entirely when the caller doesn't need it — useful for cursor-paginated user interfaces that only display the count cosmetically. The accepted values list is forward-compatible: future modes (e.g. approximate counts) can be added without breaking existing callers.
The internal QueryEntitiesInitialRequest.skipTotalItems option has been replaced by totalItems: 'include' | 'exclude'. Note that skipTotalItems was never exposed as a REST API parameter, so this is only a TypeScript-level change affecting direct callers of EntitiesCatalog.queryEntities.
Sort field keys are now lowercased before comparing against search.key, fixing silent mismatches for camelCase field names. The NULLS LAST ordering clause has been removed since NULL sort values are already excluded by the WHERE clause.
dc7678c: Removed the immediate mode stitching strategy. All stitching now uses the deferred mode, which processes entities asynchronously via a worker queue. If your configuration includes catalog.stitchingStrategy.mode: 'immediate', it will be ignored with a deprecation warning. The pollingInterval and stitchTimeout settings continue to work as before.
9698738: Dropped the legacy search_entity_id_idx index which is now redundant with the covering unique index on (entity_id, key, value). The old index caused the query planner to choose an inefficient scan pattern for catalog list queries with multiple sort fields, leading to severely degraded performance on large catalogs.
ccfa4f1: Optimized entitiesBatch on PostgreSQL to use = ANY(array) instead of WHERE IN ($1, $2, ...). This produces a single stable query plan regardless of batch size, instead of up to 200 different plans that pollute the query plan cache. On PostgreSQL, batching is no longer needed so all entity refs are fetched in a single query.
750b310: HAS_LABEL and HAS_ANNOTATION permission rules are now case insensitive.
24775dc: Added a migration that tunes PostgreSQL automatic vacuum thresholds on the search, final_entities, relations, and refresh_state_references tables, and fixes column statistics for entity_id in the search table. This prevents the query planner from falling back to sequential scans when table maintenance falls behind, keeping catalog queries fast on large installations.
39c5fbb: Added extended multi-column statistics on (key, value) in the search table (PostgreSQL only). This tells the query planner about the correlation between the key and value columns, fixing severe row count estimation errors on compound filter queries. Without this, the planner could choose to materialize and sort thousands of rows instead of using the LIMIT short-circuit index scan — causing 10-40x slower catalog list views when multiple filters are active.
4829e89: Split the queryEntities list and count into separate queries instead of a multi-reference CTE. When the filtered CTE was referenced twice (once for the count, once for the data), PostgreSQL refused to inline it, forcing full materialization of the filtered set before applying LIMIT. By running the count as a standalone query, the list CTE is only referenced once, allowing the planner to short-circuit on LIMIT and return the first page in milliseconds instead of waiting for the full filtered set to materialize.
The standalone count query also fixes a pre-existing bug where totalItems was inflated for entities with multi-valued sort fields (e.g. tags). The old CTE-based count counted search rows, so an entity with 3 tags would be counted 3 times. The new count uses EXISTS to count distinct entities, aligning totalItems with the number of entities actually reachable through cursor pagination.
774d698: Fixed a race condition in the stitch queue and entity processing claim logic where SELECT FOR UPDATE SKIP LOCKED row locks were released before the subsequent timestamp bump, allowing multiple workers to claim the same rows. Both the select and update now run inside a single transaction for MySQL and PostgreSQL.
0b8b677: Improved stitch queue semantics to prevent overlapping stitches for the same entity. New stitch requests that arrive while a stitch is in progress now only update the ticket (not the timestamp), so the in-progress worker is not interrupted. When the worker completes and detects a pending re-stitch, the queue entry becomes immediately eligible for pickup instead of waiting for the timeout period.
Updated dependencies
getOptionLabel and renderOption props to EntityAutocompletePicker, allowing consumers to customize how option labels and option rendering are displayed in the autocomplete dropdown.refresh function to the useEntityList hook.d8757b1: The entity list provider now fetches the entity list and the total count as two separate parallel requests when using cursor or offset pagination. The list query skips the expensive count computation (using totalItems: 'exclude'), so the table populates immediately. The count arrives asynchronously and updates the title. A new totalItemsLoading field is exposed on EntityListContextProps so consumers can distinguish a stale count from a fresh one.
The catalog table now keeps stale rows visible during filter changes and page navigation instead of replacing the entire table body with a spinner. The full-table spinner is only shown on the very first load when no data exists yet. The entity count in the title is dimmed while the count is refreshing, and a small spinner appears next to the title while rows are loading.
e0889a3: chore(deps): bump qs from 6.15.1 to 6.15.2
7c20545: Fixed redundant API calls during entity list initialization. Filter components that register their initial state in quick succession (e.g. EntityKindPicker, UserListPicker, EntityTagPicker) no longer trigger multiple identical fetches. Frontend-only filter changes such as toggling the user list are now applied synchronously without a network round-trip.
Updated dependencies
RepoOwnerPicker implementation with a custom variant for GitLab.qs from 6.15.1 to 6.15.2json-schema runtime dependency. The package was only used for TypeScript types from @types/json-schema; affected imports have been converted to import type to allow safe removal.74ed625: Provide toastApi for old frontend system
Fixes 'No implementation available for apiRef{core.toast}' on old frontend system.
Updated dependencies
infinispan from ^0.12.0 to ^0.13.0 to address known vulnerabilities.AzureBlobStorageUrlReader to reference the correctly-named AzureBlobStorageIntegration type from @backstage/integration. The previously-used AzureBlobStorageIntergation is now an alias for the new type and remains a valid argument to the constructor.AzureBlobStorageUrlReader now accepts an optional createContainerClient dependency for testability without needing to mock the @azure/storage-blob module.backend.rateLimit is enabled. Requests are now keyed using the address normalization helper from express-rate-limit, which is required by newer versions of that library and ensures IPv6 clients are grouped by their address block rather than by individual address.v2 invoke endpoint (/.backstage/actions/v2/actions/:id/invoke) that accepts a wrapped body format { input, secrets } with secrets validation. The existing v1 invoke endpoint remains unchanged for backward compatibility. Updated DefaultActionsService to use the v2 endpoint. Updated DefaultActionsRegistryService to expose secrets schema in the actions list response and validate secrets on invocation.package.json is present but does not provide a plugin entrypoint. Previously, plugins whose alpha export only exposed supplementary APIs (such as permissions) could fail to load even though the main export was valid. The loader now tries the alpha entry first and uses the main export when the alpha module does not export a BackendFeature, BackendFeatureFactory, or dynamicPluginInstaller.json-schema runtime dependency. The package was only used for TypeScript types from @types/json-schema; affected imports have been converted to import type to allow safe removal.secrets schema support to ActionsRegistryActionOptions and ActionsRegistryActionContext. Actions can now declare a Zod secrets schema separate from the input schema, enabling surfaces to collect sensitive credentials independently from tool arguments. Added optional secrets field to ActionsServiceAction metadata and ActionsService.invoke() parameters.connect ETIMEDOUT failures in CI. The test MySQL container now also uses mysql_native_password for cheaper connection handshakes and disables binary logging.MockActionsRegistry to support the new secrets schema. The mock now validates secrets against the declared schema, rejects missing secrets for actions that require them, and forwards secrets to the action handler.--help output for commands now shows a generated usage line that lists the available flags and any positional arguments the command accepts.--help output for commands now shows a generated usage line that lists the available flags and any positional arguments the command accepts.--help output for commands now shows a generated usage line that lists the available flags and any positional arguments the command accepts.@protobufjs/inquire "Critical dependency" warning in the bundler. Since protobufjs 7.5.9, the dynamic require path in inquire is no longer exercised, but webpack/rspack still flags it during static analysis.embedded-postgres to 18.3.0-beta.17.--help output for commands now shows a generated usage line that lists the available flags and any positional arguments the command accepts.json-schema runtime dependency. The package was only used for TypeScript types from @types/json-schema; affected imports have been converted to import type to allow safe removal.--help output for commands now shows a generated usage line that lists the available flags and any positional arguments the command accepts.--help output for commands now shows a generated usage line that lists the available flags and any positional arguments the command accepts.--help output for commands now shows a generated usage line that lists the available flags and any positional arguments the command accepts.--help output for commands now shows a generated usage line that lists the available flags and any positional arguments the command accepts.--help output for commands now shows a generated usage line that lists the available flags and any positional arguments the command accepts.scaffolder-field-extension-module template for scaffolding custom Scaffolder form field extensions via backstage-cli new.--help output for commands now shows a generated usage line that lists the available flags and any positional arguments the command accepts.--help output for commands now shows a generated usage line that lists the available flags and any positional arguments the command accepts.--help output for commands now shows a generated usage line that lists the available flags and any positional arguments the command accepts.runCli for creating executable CLI packages from a fixed collection of directly imported CLI modules, with validation for conflicting command paths. The single-module runCliModule helper is now deprecated.json-schema runtime dependency. The package was only used for TypeScript types from @types/json-schema; affected imports have been converted to import type to allow safe removal.qs from 6.15.1 to 6.15.2'header' literal to the TableFiltersClassKey union type and deprecated the previous typoed 'heder' literal. The generated CSS class with the old key is preserved for backwards compatibility; switch to 'header' to avoid future removal.react-syntax-highlighter and @dagrejs/dagre so they are no longer pulled in eagerly through the barrel export. This reduces the upfront module cost of importing from @backstage/core-components by roughly 10 MB. The public API is unchanged.68db890: Bumped create-app version.
e7e4ef0: Bumped create-app version.
6344c54: Newly scaffolded apps now use Yarn 4.13.0 (up from 4.4.1) and enable Yarn's npmMinimalAgeGate: 3d setting, which refuses to install npm packages published less than three days ago as a defense against supply-chain attacks. Backstage's own packages are exempted via npmPreapprovedPackages: ['@backstage/*'] so newly released Backstage versions remain installable without delay.
Existing apps are unaffected. To opt in, add the npmMinimalAgeGate and npmPreapprovedPackages settings to your own .yarnrc.yml and upgrade Yarn to 4.13 or later.
@backstage/no-deprecated-bui-tokens lint rule that warns when a deprecated @backstage/ui CSS token is referenced in a JavaScript or TypeScript file (including CSS-in-JS patterns and template literals). The rule is included in the recommended config, so plugin authors using plugin:@backstage/recommended will receive warnings automatically when using tokens that have been superseded by the new semantic color families. Note that plain CSS and CSS module files are outside ESLint's scope and are not covered by this rule.devDependencies to dependencies. These were incorrectly demoted in #33936 because the source code only uses type imports, but the types still appear in the published API surface and need to be resolvable by consumers at build time.mountPath option to renderInTestApp that controls the route path pattern the test element is rendered at. When set, the element is wrapped in a <Route> with the given path, enabling useParams() to extract route parameters from the URL. Use together with initialRouteEntries to set a concrete URL that matches the pattern. This is useful for testing page components that depend on URL parameters, such as entity pages that use useRouteRefParams.AzureBlobStorageIntegration class export and deprecated the previous typoed AzureBlobStorageIntergation export. Existing usage of AzureBlobStorageIntergation continues to work; switch to AzureBlobStorageIntegration to avoid future removal.AzureBlobStorageUrlReader now accepts an optional createContainerClient dependency for testability without needing to mock the @azure/storage-blob module.app.disablePublicEntryPoint config option that allows you to opt out of the automatic public sign-in entry point. When set to true, the app backend will skip serving the public entry point to unauthenticated users, even if the app was bundled with an index-public-experimental entry point.7172386: Updated the new frontend system Catalog index page to use the current Backstage UI page header and content container.
d8757b1: The entity list provider now fetches the entity list and the total count as two separate parallel requests when using cursor or offset pagination. The list query skips the expensive count computation (using totalItems: 'exclude'), so the table populates immediately. The count arrives asynchronously and updates the title. A new totalItemsLoading field is exposed on EntityListContextProps so consumers can distinguish a stale count from a fresh one.
The catalog table now keeps stale rows visible during filter changes and page navigation instead of replacing the entire table body with a spinner. The full-table spinner is only shown on the very first load when no data exists yet. The entity count in the title is dimmed while the count is refreshing, and a small spinner appears next to the title while rows are loading.
82cf16f: Added CatalogExportButton, which adds CSV and JSON export support to the CatalogIndexPage.
d7c1dcf: Fixed a missing React key warning for context menu items on the entity page.
a07e6a3: Added the correctly-spelled RelatedEntitiesCard.domainEntityColumns static property and deprecated the previous typoed RelatedEntitiesCard.domainEntityColums property. Existing references to the old property continue to work; switch to domainEntityColumns to avoid future removal.
Updated dependencies
AzureBlobStorageIntegration (previously misspelled as AzureBlobStorageIntergation) following the rename in @backstage/integration.analyzeBitbucketServerWebhookEvent function is exported from the alpha entry point for custom integrations.ingestions.last_error to remove the 255-character restriction.qs from 6.15.1 to 6.15.2user.select to an empty array would cause all users to be dropped from the catalog instead of using the default set of fields.accountEnabled eq true base filter that was added in v1.51.0, which broke the userGroupMember path because the group members endpoint doesn't support $filter on that property. Disabled users (accountEnabled === false) are now filtered client-side in both the /users and group members paths. The mutual exclusivity checks between userFilter and userGroupMemberFilter/userGroupMemberSearch have been restored.$ref paths in OpenAPI and AsyncAPI specs by using the original reference string and parent document URL from the ref parser, instead of computing paths relative to the process working directory. This fixes a regression where cross-directory refs like ./../../common/specs/common.yaml and nested refs at depth > 1 would resolve incorrectly.qs from 6.15.1 to 6.15.2catalog-unprocessed-entities page'widgetSettingsOverlay.editSettingsTooltip' translation key in homeTranslationRef and deprecated the previous typoed 'widgetSettingsOverlay.editSettingsTooptip' key. Existing references to the old key continue to work; switch to the new key to avoid future removal./kubernetes. This page was added by mistake and is not intended to be part of the plugin.ws from 8.20.0 to 8.20.1tools/list, and skip any action that doesn't conform instead of failing the entire response. A single misbehaving action with a malformed input schema will now be logged as a warning and omitted from the tool list, letting the remaining actions continue to be served.qs from 6.15.1 to 6.15.2publish:github and github:repo:push actions that retries via the GitHub GraphQL API when the git push fails with a connection-level error (ECONNRESET or ECONNREFUSED, checked on both error.code and error.cause.code). The git smart HTTP protocol sends binary pack data in a POST request which can be blocked by network proxies that perform deep packet inspection. The GraphQL fallback uses standard JSON requests which are not affected.json-schema runtime dependency. The package was only used for TypeScript types from @types/json-schema; affected imports have been converted to import type to allow safe removal.Git.push(). Scaffolder template actions that create a repository and immediately push to it (e.g., publish:github) can encounter transient failures when the repository is not yet fully provisioned. The push is now retried up to 5 times with increasing delays before failing. Authentication and permission errors (401, 403) fail immediately without retrying.qs from 6.15.1 to 6.15.2json-schema runtime dependency. The package was only used for TypeScript types from @types/json-schema; affected imports have been converted to import type to allow safe removal.qs from 6.15.1 to 6.15.2qs from 6.15.1 to 6.15.2qs from 6.15.1 to 6.15.2qs from 6.15.1 to 6.15.2ws from 8.20.0 to 8.20.1460c597: Added missing i18n support for TechDocs plugin components including:
Also exported techdocsTranslationRef from the alpha entrypoint for external use.
Updated dependencies
/alpha entrypoint that bundles all contributed TechDocs addon modules using createFrontendFeatureLoader. This allows the package to be loaded as a single feature in setups that discover frontend modules through their default export, such as dynamic plugin loaders.