Root Cause Analysis: Undefined Module Export Error
Date: 2025-11-19 Status: ✅ RESOLVED Severity: CRITICAL - Backend start failure
Error Signature
Cannot use 'in' operator to search for '$$type' in undefined
Location: @backstage/backend-app-api/src/wiring/helpers.ts:23:7
Root Cause
The module export is NOT actually undefined. The real issue is a transitive dependency import failure:
Import Chain Analysis
packages/backend/src/index.ts
└─> import('@internal/plugin-terraform-state-backend')
└─> dist/index.cjs.js (exports catalogModuleTerraformStateTfcProvider ✅)
└─> dist/modules/tfcModule.cjs.js ✅
└─> dist/providers/TfcStateProvider.cjs.js ✅
└─> dist/services/VaultTokenService.cjs.js ❌
└─> FAILS: Cannot find module '@internal/backstage-plugin-vault-secrets-backend/src/service/VaultClient'
The Problem
File: plugins/terraform-state-backend/src/services/VaultTokenService.ts:8
// ❌ WRONG: Deep import into package internals
import { VaultClient } from '@internal/backstage-plugin-vault-secrets-backend/src/service/VaultClient';
Issue: The vault plugin does NOT export VaultClient from its package entry point.
Vault Plugin Exports (@internal/backstage-plugin-vault-secrets-backend/src/index.ts):
export { vaultSecretsPlugin as default } from './plugin';
// VaultClient is NOT exported!
Why This Causes "Undefined" Error
- Backend tries to load terraform-state-backend module
- Module import chain fails at VaultTokenService dependency
- The entire module object becomes
undefineddue to the failed import - Backstage's
backend.add()unwrapping function tries to access$$typeproperty - Error:
Cannot use 'in' operator to search for '$$type' in undefined
Solution Options
Option 1: Export VaultClient from Vault Plugin (RECOMMENDED)
Modify: plugins/backstage-plugin-vault-secrets-backend/src/index.ts
export { vaultSecretsPlugin as default } from './plugin';
export { VaultClient } from './service/VaultClient';
export type { VaultConfig, VaultSecret } from './service/VaultClient';
Then update: plugins/terraform-state-backend/src/services/VaultTokenService.ts
// ✅ CORRECT: Import from package entry point
import { VaultClient } from '@internal/backstage-plugin-vault-secrets-backend';
Option 2: Create Shared Vault Service Package
Create a dedicated package for shared vault utilities that both plugins can depend on.
Option 3: Inline VaultClient (NOT RECOMMENDED)
Duplicate the VaultClient code in terraform-state-backend (violates DRY principle).
Code Quality Issues Identified
1. Deep Imports Anti-Pattern
Severity: HIGH
Using deep imports (package/src/internal/module) is an anti-pattern because:
- Breaks package encapsulation
- Couples to internal implementation details
- Fails when dependencies aren't built or available
- Makes refactoring difficult
Location: Multiple files in terraform-state-backend
2. Incomplete Package Exports
Severity: MEDIUM
The vault-secrets-backend plugin only exports the plugin itself, not shared utilities.
Impact: Forces consumers to use deep imports or duplicate code
3. Missing Dependency Validation
Severity: MEDIUM
No build-time or runtime validation that required exports are available.
Recommendation: Add TypeScript type checking or runtime validation
Fix Implementation
The fix requires updating both plugins:
- Vault Plugin - Export VaultClient
- Terraform State Plugin - Update import to use package exports
- Both Plugins - Rebuild with
yarn build
Prevention
Build-Time Checks
Add to package.json scripts:
{
"scripts": {
"typecheck": "tsc --noEmit",
"prebuild": "yarn typecheck"
}
}
Linting Rules
Add ESLint rule to prevent deep imports:
{
"rules": {
"no-restricted-imports": [
"error",
{
"patterns": ["@internal/*/src/*"]
}
]
}
}
Related Files
/packages/backend/src/index.ts:108- Backend registration/plugins/terraform-state-backend/src/index.ts- Module export (correct)/plugins/terraform-state-backend/src/modules/tfcModule.ts- Module definition (correct)/plugins/terraform-state-backend/src/services/VaultTokenService.ts:8- INVALID IMPORT/plugins/backstage-plugin-vault-secrets-backend/src/index.ts- MISSING EXPORT
Status: READY FOR FIX
All analysis complete. Recommended approach: Option 1 (export from vault plugin).
Analysis By: Code Quality Analyzer (Hive Mind) Task ID: task-1763526192977-oajcdxtkg