Troubleshooting
Issues you will most likely run into when installing the OpenChoreo plugins into an existing Backstage app, drawn from observed failures.
Missing alpha.core.metrics service ref
Service or extension point dependencies of plugin 'catalog' are missing
for the following ref(s): serviceRef{alpha.core.metrics}
Cause: your host app resolved a newer minor of @backstage/plugin-catalog-backend than the OpenChoreo plugins were tested against. Newer versions depend on alpha services (alpha.core.metrics, catalogPermissionExtensionPoint) that the older backend-defaults does not provide.
Fix: pin every @backstage/* package to the version line tested by OpenChoreo. The full set is in the compatibility matrix. Add the listed resolutions to your workspace root package.json, then:
rm -rf node_modules yarn.lock
yarn install
Missing catalog.permission extension point
Service or extension point dependencies of module 'openchoreo' for plugin
'catalog' are missing for the following ref(s): extensionPoint{catalog.permission}
Same root cause as above. The catalogPermissionExtensionPoint is registered by @backstage/plugin-catalog-backend@3.1.x; in 3.6.x+ it moved out of the main package. Pin to 3.1.1.
AnnotationStore is not available
Failed to instantiate service 'openchoreo.annotation-store' because the
default factory loader threw an error, Error: AnnotationStore is not
available. Make sure the catalog-backend-module-openchoreo is installed.
Cause: the catalog-backend-module is installed but the service factories are not registered. The factories are required by both catalog-backend-module-openchoreo (for processors) and openchoreo-backend (for the API surface).
Fix: add the explicit backend.add(...) lines in packages/backend/src/index.ts:
import {
immediateCatalogServiceFactory,
annotationStoreFactory,
} from "@openchoreo/backstage-plugin-catalog-backend-module";
backend.add(immediateCatalogServiceFactory);
backend.add(annotationStoreFactory);
These must be added before backend.start().
openchoreo.schedule.frequency config rejected as object
Invalid type in config for key 'openchoreo.schedule.frequency' in
'app-config.local.yaml', got object, wanted number
Cause: the catalog provider expects frequency and timeout to be plain integers (seconds), not the Backstage HumanDuration shape.
Fix:
openchoreo:
schedule:
frequency: 30 # ✅ correct
timeout: 120 # ✅ correct
# frequency: { seconds: 30 } ❌ wrong — produces this error
Catalog sync fails with 401 from OpenChoreo
Failed to fetch namespaces: 401 Unauthorized - missing or invalid
authentication token
Cause: the catalog provider tried to call the OpenChoreo API without a token. This happens when either openchoreo.features.auth.enabled is false or the OAuth clientId / clientSecret / tokenUrl are missing or wrong.
Fix: keep auth.enabled: true and confirm the credentials work:
curl -X POST -d 'grant_type=client_credentials' \
-d "client_id=${OPENCHOREO_CLIENT_ID}" \
-d "client_secret=${OPENCHOREO_CLIENT_SECRET}" \
${OPENCHOREO_TOKEN_URL}
A successful response returns a JSON object with access_token. If you see invalid_client, the credentials are wrong; if the request times out, the IDP is not reachable.
Yarn portal: link conflicts on @backstage/*
Cannot link @openchoreo/backstage-plugin-react ... dependency
@backstage/catalog-model conflicts with parent dependency
Cause: you tried to use Yarn portal: to point at a sibling openchoreo/backstage-plugins checkout. Portal preserves each portal'd workspace's own node_modules, which produces duplicate @backstage/* package instances and broken service-ref identity.
Fix: install from GitHub Packages instead of using portal:. See the installation guide — yarn add against the published @openchoreo/* packages lets yarn dedupe @backstage/* against your host app's tree.
React duplicate-instance error / "Invalid hook call"
Cause: two copies of react in the dependency tree, usually because a portal'd or link:-ed plugin pulled its own react instead of using the host's.
Fix: add to your workspace root resolutions:
"resolutions": {
"react": "18.3.1",
"react-dom": "18.3.1",
"@types/react": "18.3.26",
"@types/react-dom": "18.3.7"
}
csstype type errors during yarn tsc
Property.AlignmentBaseline ... is not assignable
Cause: version drift on csstype between the OpenChoreo plugin tree and your app's tree.
Fix:
"resolutions": {
"csstype": "3.1.3"
}
Backend module startup fails with Cannot read properties of undefined (reading 'id')
Module 'openchoreo' for plugin 'catalog' startup failed;
caused by TypeError: Cannot read properties of undefined (reading 'id')
Cause: one of the modules registered with backend.add(...) declares a dependency on a service ref that resolved to undefined. Usually a version skew where one of @backstage/plugin-scaffolder-backend-module-notifications or similar is pulled at a version newer than your Backstage release line.
Fix: pin all transitive @backstage/* resolutions to the tested versions in the compatibility matrix. If you do not need a specific module (e.g. scaffolder-backend-module-notifications), remove its backend.add(...) line and yarn remove it.
Port 7007 already in use
EADDRINUSE: address already in use :::7007
A previous failed boot left a node process on port 7007. Kill it:
lsof -i :7007 -i :3000
kill <pid>
Catalog provider runs but no entities show up
Check catalog.rules.allow includes Domain and any other custom kinds the OpenChoreo provider produces. The catalog silently drops disallowed kinds.
catalog:
rules:
- allow: [Component, System, Domain, API, Resource, Location, Group, User]
NotificationsSidebarItem crashes the app at boot
Uncaught TypeError: Cannot read properties of undefined (reading 'id')
in <NotificationsSidebarItem>
Cause: the create-app template installs @backstage/plugin-notifications, which in versions newer than the 1.43.3 release line expects exports (toastApiRef, Tag, Dialog, DialogHeader, ...) that the pinned @backstage/ui and @backstage/frontend-plugin-api do not provide.
Fix: remove NotificationsSidebarItem from packages/app/src/components/Root/Root.tsx and <NotificationsPage /> from packages/app/src/App.tsx. See the installation guide for details.
choreoPlugin API factories not registered on entity tabs
NotImplementedError: No implementation available for
apiRef{plugin.openchoreo.client}
Cause: Backstage's plugin auto-discovery walks the JSX tree of the rendered app to find plugins. The Environments and CellDiagram components are mounted inside EntitySwitch.Case branches that only render once an entity is loaded, so they are not in the static tree at app boot. Backstage never adds choreoPlugin to its plugin set, and its apis: [...] factories are never registered.
Fix: register choreoPlugin explicitly in packages/app/src/App.tsx:
import { choreoPlugin } from "@openchoreo/backstage-plugin";
const app = createApp({
apis,
plugins: [choreoPlugin],
// ...
});
Observability API factory missing on Environments tab
NotImplementedError: No implementation available for
apiRef{plugin.openchoreo-observability.service}
Cause: the Deploy tab tries to render incident chips but no factory is registered for the observability API. The Core plugin resolves this API lazily via useApiHolder().get(), so the tab itself renders fine without observability — but if something else in your app force-references the API, or you're on a build that uses useApi(), you get this throw.
Fix: install the observability tab pack as documented in the installation guide → Observability tabs. It registers the API factory and feeds real incident data into the same UI.
openchoreo-auth provider misconfigured
NotFoundError: Auth provider registered for 'openchoreo-auth' is misconfigured.
This could mean the configs under auth.providers.openchoreo-auth are missing
or the environment variables used are not defined.
Cause: one or more of the OPENCHOREO_AUTH_* env vars referenced by auth.providers.openchoreo-auth.development.* in your app-config.local.yaml is undefined. Backstage's config loader expands ${VAR} placeholders at startup; if a var is missing, the literal ${OPENCHOREO_AUTH_CLIENT_ID} string ends up in the config, and the auth module rejects it.
Fix: for local k3d, hardcode the seeded credentials instead of using env-var substitution — see the Local k3d quickstart section. For a real deployment, set the env vars in your shell or process manager before starting Backstage.
401 on tab data fetches after signing in
HTTP 401: Unauthorized
Cause: you're signed in to Backstage but the OpenChoreo backend modules (-observability-backend, -ci-backend, -workflows-backend) reject your requests because they can't find the IDP token. Backstage's default fetchApi only injects the Backstage identity token in Authorization; it has no concept of the x-openchoreo-token header the backend modules read.
Fix: install the custom OpenChoreoFetchApi and register it against fetchApiRef. See Override fetchApi. The same fix is needed for permission requests — see Override permissionApi.
"No permissions to view this environment" on Deploy / Logs / Metrics tabs
Cause: one of two things, in order of likelihood:
OpenChoreoPermissionApinot registered inpackages/app/src/apis.ts. The defaultPermissionClientbypassesfetchApientirely and never gets the IDP token, so every authorize call fails. Fix: OverridepermissionApi.- Your user genuinely has no capabilities in OpenChoreo. The IDP token is valid but the user's entitlements from ThunderID have not been mapped to a role in OpenChoreo that grants
release-binding:read/environment:read. Confirm withLOG_LEVEL=debug yarn start, hit a Deploy tab, and grep backend logs for[AUTHZ] Parsed capabilities— that dumps what the OpenChoreo authz service returned. If the expected capabilities aren't there, fix the user's role bindings on the OpenChoreo control plane, not in Backstage.
JWKSNoMatchingKey warnings in permission backend logs
permission warn Failed to verify incoming user token no applicable key
found in the JSON Web Key Set
Benign. It means the permission backend is trying to verify an incoming user token against the OpenChoreo IDP's JWKS but the token was issued by another provider (typically Backstage's guest provider when your cluster is in auth-off mode). Catalog sync still works because the catalog provider uses its own client-credentials flow, not the user token. The warning disappears once users sign in via OpenChoreo (i.e. when the cluster runs with auth.enabled: true and your Backstage config mirrors it).