From 1c1347a827d88908fe06f78cde737b1f434ef11b Mon Sep 17 00:00:00 2001 From: Brian Hudson Date: Wed, 13 Aug 2025 07:17:45 -0400 Subject: [PATCH] Fix feature discovery crash with packages using modern Node.js exports fields When using packages that employ modern Node.js "exports" fields without exporting ./package.json (such as OpenTelemetry packages), the feature discovery service crashes with ERR_PACKAGE_PATH_NOT_EXPORTED errors. This happens because these packages restrict which files can be accessed via require(), and many don't expose their package.json files. Wraps the package.json resolution with error handling to gracefully skip packages that don't export their package.json. Since these packages can't be Backstage plugins anyway (we need access to the backstage.role field). Signed-off-by: Brian Hudson --- .../src/PackageDiscoveryService.ts | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/packages/backend-defaults/src/PackageDiscoveryService.ts b/packages/backend-defaults/src/PackageDiscoveryService.ts index 90e8d0f59d..ef95bc9f5e 100644 --- a/packages/backend-defaults/src/PackageDiscoveryService.ts +++ b/packages/backend-defaults/src/PackageDiscoveryService.ts @@ -125,9 +125,22 @@ export class PackageDiscoveryService { const features: BackendFeature[] = []; for (const name of dependencyNames) { - const depPkg = require(require.resolve(`${name}/package.json`, { - paths: [packageDir], - })) as BackstagePackageJson; + let depPkg: BackstagePackageJson; + try { + const packageJsonPath = require.resolve(`${name}/package.json`, { + paths: [packageDir], + }); + depPkg = require(packageJsonPath) as BackstagePackageJson; + } catch (error) { + // Handle packages with "exports" field that don't export ./package.json + if ( + error instanceof Error && + (error as any).code === 'ERR_PACKAGE_PATH_NOT_EXPORTED' + ) { + continue; // Skip packages that don't export package.json - they can't be Backstage packages + } + throw error; + } if ( !depPkg?.backstage?.role || !DETECTED_PACKAGE_ROLES.includes(depPkg.backstage.role)