Node.js 26 Compatibility Issues Report
Project: loopback4-microservice-catalog
Node Version Tested: 26.2.0
Executive Summary
The project is NOT ready for Node.js 26 due to dependency ecosystem issues. After updating CI workflows and package.json files to support Node 26, testing revealed multiple compatibility issues that prevent successful installation and build.
Root Cause: Node 26 introduced stricter ES module handling and API changes that exposed issues in unmaintained dependencies.
Why Didn't This Happen Before?
Node 22/24 vs Node 26:
| Aspect |
Node 22/24 |
Node 26 |
| ESM Enforcement |
Lenient - allowed some inconsistencies |
STRICT - no exceptions |
| Module Resolution |
More forgiving |
Follows spec exactly |
| Package Subpath Exports |
Partial support |
Full support required |
| Warning Visibility |
Fewer warnings |
More warnings shown |
The Key Changes:
- ESM Strict Mode -
require() illegal in ES modules
- Package Exports - Must use proper moduleResolution
- API Changes - Dependencies may have breaking updates
- More Warnings - Deprecation notices visible
Summary: All Issues Are Dependency-Related
No actual application code changes required (no .ts or .js file changes needed in your source code).
| Issue |
Type |
What's Broken |
Fix Location |
| #1 |
Dependency |
yargs package ESM incompatibility |
package.json (override) |
| #2 |
Dependency |
copyfiles package uses old yargs API |
External package |
| #3 |
Dependency |
widdershins package uses old yargs API |
External package |
| #4 |
Configuration |
TypeScript moduleResolution |
tsconfig.json |
| #5 |
Warning |
localStorage path |
Node runtime |
| #6 |
Warning |
AWS SDK v2 deprecated |
External package |
The "code changes" needed are only in:
- External dependencies (yargs, copyfiles, widdershins)
- Build configuration (tsconfig.json, package.json scripts)
- NOT in your actual TypeScript/JavaScript source code
Why Problems Now? - Detailed Analysis
The Root Cause Chain
Node 26 Released
↓
Stricter ESM enforcement
↓
yargs@17.x breaks (ESM incompatibility)
↓
Must upgrade to yargs@18.x
↓
yargs@18.x has different API
↓
Old packages expecting yargs@17 API break:
- copyfiles ❌
- widdershins ❌
Complete Issue List with "Why Now" Analysis
Issue #1: yargs ESM Incompatibility
What is yargs?
A Node.js package for parsing command-line arguments. Used by hundreds of npm packages.
How it worked before (Node 22/24):
yargs@17.7.2
├── package.json has "type": "module" (ES module)
├── But code uses require() syntax (CommonJS)
└── Node 22/24: Lenient - allowed this mismatch
Why it breaks now (Node 26):
Node 26: STRICT enforcement
├── "type": "module" means ONLY import/export allowed
├── require() is ILLEGAL in ES modules
└── Throws error immediately
The Error:
ReferenceError: require is not defined in ES module scope
at file:///node_modules/yargs/yargs:3:69
Proper Solution:
Upgrade to yargs@18.x which has proper ES module support.
BUT → This creates new problems (Issues #2 and #3)
Status: 🟡 Partially Fixed (upgraded to 18.x, but created downstream issues)
Error:
ReferenceError: require is not defined in ES module scope
at file:///node_modules/yargs/yargs:3:69
Description: yargs@17.7.2 has "type": "module" in package.json but uses require() syntax, which is invalid in ES modules with Node 26's stricter enforcement.
Fix Applied: Upgraded to yargs@18.0.0 via package.json override
"overrides": {
"yargs": "^18.0.0"
}
Result: Fixed yargs itself, but broke dependent packages (see issues #2 and #3).
Issue #2: copyfiles Package - yargs API Incompatibility
Status: 🔴 BLOCKING
What is copyfiles?
A package that copies files in your project. Used by @sourceloop/cli to copy template files.
How it worked before (Node 22/24):
// copyfiles@2.4.1 code
const yargs = require("yargs"); // Gets yargs object
// This line works with yargs 17.x:
yargs.alias("u", "up"); // ✅ Method exists on yargs object
Why it breaks now (Node 26 + yargs 18.x):
// With yargs 18.x
const yargs = require("yargs"); // Gets a FUNCTION, not an object
// This line now fails:
yargs.alias("u", "up"); // ❌ Error: alias is not a function
// Functions don't have .alias() method
The API Change:
// yargs 17.x API (old) - copyfiles uses this
const yargs = require("yargs"); // Returns object
yargs.alias("u", "up"); // ✅ Works
// yargs 18.x API (new) - required for Node 26
const yargs = require("yargs")(); // Must CALL the function
yargs.alias("u", "up"); // ✅ Works after calling
The Error:
/Users/sourav.kashyap/Desktop/Mcp/loopback4-microservice-catalog/node_modules/copyfiles/copyfiles:6
args.alias('u', 'up')
^
TypeError: args.alias is not a function
Why copyfiles breaks:
copyfiles was written 3+ years ago and expects the old API. The package is unmaintained - no updates.
Affected Package: @sourceloop/cli@12.2.6 build process
Code Location: packages/cli/package.json
"copydeps": "copyfiles -a --up 1 src/**/templates/** lib"
Package Status: ⚠️ Unmaintained (last update 3+ years ago)
Build Command Affected: npm run afterinstall, lerna run build
Proper Solution:
Replace copyfiles with maintained alternative like cpy.
Options:
- Fork and patch
copyfiles for yargs 18 compatibility
- Replace with alternative package (
cpy)
- Remove dependency on copyfiles
Issue #3: widdershins Package - yargs API Incompatibility
Status: 🔴 BLOCKING
What is widdershins?
Converts OpenAPI JSON specs to Markdown documentation for API docs.
How it worked before (Node 22/24):
// widdershins@4.0.1 code
const yargs = require("yargs");
// This works with yargs 17.x:
yargs.usage("widdershins [options]..."); // ✅ Method exists
Why it breaks now (Node 26 + yargs 18.x):
// With yargs 18.x
const yargs = require("yargs"); // Gets a FUNCTION
// This line fails:
yargs.usage("widdershins [options]..."); // ❌ Error: usage is not a function
The Error:
/Users/sourav.kashyap/Desktop/Mcp/loopback4-microservice-catalog/node_modules/widdershins/widdershins.js:14
.usage('widdershins [options] {input-file|url} [[-o] output markdown]')
^
TypeError: require(...).usage is not a function
Why widdershins breaks:
Same problem as copyfiles - expects yargs 17.x API, package is unmaintained.
Package Status: ⚠️ Unmaintained
Build Command Affected: lerna run build, npm run afterinstall
Affected Services (16 total):
@sourceloop/audit-service
@sourceloop/authentication-service
@sourceloop/bpmn-service
@sourceloop/chat-service
@sourceloop/in-mail-service
@sourceloop/notification-service
@sourceloop/oidc-service
@sourceloop/payment-service
@sourceloop/reporting-service
@sourceloop/scheduler-service
@sourceloop/search-service
@sourceloop/survey-service
@sourceloop/task-service
@sourceloop/user-tenant-service
@sourceloop/video-conferencing-service
- And others...
Code Pattern (in each service):
"apidocs": "npx widdershins --language_tabs 'javascript:JavaScript:request' 'javascript--nodejs:Node.JS' --summary openapi.json -o openapi.md"
Proper Solution:
Either:
- Replace with alternative (no direct replacement exists)
- Skip apidocs generation (use OpenAPI JSON directly)
- Fork and patch widdershins
Options:
- Fork and patch
widdershins for yargs 18 compatibility
- Replace with alternative OpenAPI to Markdown converter
- Skip apidocs generation temporarily
Issue #4: OpenTelemetry Module Path Issue
Status:
What is this?
TypeScript trying to find @opentelemetry/semantic-conventions/incubating module.
How it worked before (Node 22/24):
TypeScript with CommonJS moduleResolution
├── Looks for files with .js extension
├── Doesn't understand package.exports field well
└── Node 22/24: More lenient path resolution
Why it breaks now (Node 26):
Node 26 + newer TypeScript
├── package.json has subpath export:
│ "./incubating": "./build/src/index-incubating.js"
├── Old moduleResolution: "node" - ignores exports field
└── Can't find the module
The Package Export Structure:
// @opentelemetry/semantic-conventions package.json
{
"exports": {
".": "./build/src/index.js",
"./incubating": "./build/src/index-incubating.js" // ← This path
}
}
Original Error:
src/profiles/otlp.profile.ts(15,43): error TS2307: Cannot find module '@opentelemetry/semantic-conventions/incubating' or its corresponding type declarations.
The Import:
// packages/observability/src/profiles/otlp.profile.ts
import { ATTR_DEPLOYMENT_ENVIRONMENT } from "@opentelemetry/semantic-conventions/incubating";
Affected Package: @sourceloop/observability@0.0.1
Code Location: packages/observability/src/profiles/otlp.profile.ts:15
Fix Applied: Updated packages/observability/tsconfig.json:
{
"compilerOptions": {
"moduleResolution": "Node16",
"module": "Node16"
}
}
Build Command Affected: npm run afterinstall, lerna run build
Result:
Note: Node16 moduleResolution properly handles package.exports field.
Issue #5: localStorage Warning
Status: ⚠️ WARNING (Non-blocking)
What is this?
Node 26 Web Storage API warning for localStorage.
How it worked before (Node 22/24):
localStorage available by default
├── No explicit configuration needed
└── No warnings shown
Why warning appears now (Node 26):
Node 26 Web Storage API changes
├── localStorage requires explicit configuration
├── Must specify --localstorage-file path
└── Shows warning if not configured
The Warning:
ExperimentalWarning: localStorage is not available because --localstorage-file was not provided.
(Use `node --trace-warnings ...` to show where the warning was created.)
Description: Node 26 Web Storage API requires explicit file path for localStorage.
Affected: Services using node ./dist/openapi-spec command
Severity: LOW - Warning only, does not block builds
Build Commands Affected: npm run afterinstall, lerna run build
Proper Solution:
Either ignore (warning only) or add --localstorage-file flag to Node commands.
Issue #6: AWS SDK v2 End-of-Support Warning
Status: ⚠️ WARNING (Non-blocking)
What is this?
AWS SDK for JavaScript v2 has reached end-of-support.
How it worked before (Node 22/24):
AWS SDK v2 worked fine
├── No deprecation warnings
└── Node didn't show EOL notices
Why warning appears now (Node 26):
Node 26 shows more warnings
├── AWS SDK v2 is deprecated
└── Node 26 displays the EOL notice
The Warning:
(node:XXXX) NOTE: The AWS SDK for JavaScript (v2) has reached end-of-support.
It will no longer receive updates or releases.
Please migrate your code to use AWS SDK for JavaScript (v3).
For more information, check the blog post at https://a.co/cUPnyil
Description: AWS SDK v2 has reached end-of-life.
Severity: LOW - Deprecation warning only
Recommendation: Plan migration to AWS SDK v3
Build Commands Affected: Services using AWS SDK
Proper Solution:
Plan migration to AWS SDK v3 (not urgent).
Issue Status Summary
| Issue |
Package |
Status |
Severity |
Fix Required |
| #1 |
yargs 17.x |
🟡 Partially Fixed |
HIGH |
Created downstream issues |
| #2 |
copyfiles |
❌ BLOCKING |
HIGH |
Replace or patch |
| #3 |
widdershins |
❌ BLOCKING |
HIGH |
Replace or skip |
| #4 |
OpenTelemetry |
❌ BLOCKING |
- |
ModuleResolution updated |
| #5 |
localStorage |
⚠️ Warning |
LOW |
Optional fix |
| #6 |
AWS SDK v2 |
⚠️ Warning |
LOW |
Migration to v3 |
Dependency Chain Problem
Your Project (Node 26)
│
├─> yargs 17.x ❌ (ESM incompatibility)
│ └─> yargs 18.x ✅ (Node 26 compatible)
│ BUT ↓
│ Breaks packages expecting yargs 17 API
│
├─> @sourceloop/cli
│ └─> copyfiles ❌ (expects yargs 17 API)
│
└─> All services (16)
└─> widdershins ❌ (expects yargs 17 API)
The JavaScript/npm dependency ecosystem creates chains. When yargs upgraded to 18.x for Node 26 compatibility, it broke packages using the old API.
yargs API Changes (17.x → 18.x)
The upgrade from yargs 17 to 18 introduced breaking API changes:
// yargs 17.x (old API)
const yargs = require("yargs");
yargs.alias("v", "version"); // ✅ Works
yargs.usage("Description"); // ✅ Works
// yargs 18.x (new API)
const yargs = require("yargs");
yargs.alias("v", "version"); // ❌ Error: alias is not a function
yargs.usage("Description"); // ❌ Error: usage is not a function
// Correct usage in 18.x:
const yargs = require("yargs")(); // Note: () - call as function
yargs.alias("v", "version"); // ✅ Now works
yargs.usage("Description"); // ✅ Now works
Packages like copyfiles and widdershins need to be updated to call yargs() as a function first.
Resolution Options
Option 1: Replace Dependencies 🔄
Effort: High
copyfiles replacement:
cpy - Active maintenance
- Custom Node.js script
widdershins alternatives:
@apidevtools/swagger-parser + custom markdown generator
redoc for HTML documentation
- Skip apidocs, use JSON OpenAPI spec only
Pros: Modern, maintained packages
Cons: Significant code changes required
Option 2: Skip apidocs Generation 📝
Effort: Low
- Comment out
apidocs script in all affected services
- Keep
openapi-spec (JSON generation works fine)
- Revisit later when ecosystem improves
Pros: Unblocks builds immediately
Cons: No markdown documentation
Option 3: Stay on Node 22/24 ✅
Effort: None
- Revert yargs override
- Keep Node 22 and 24 support only
- Revisit Node 26 in 12 months
Pros: Everything works now
Cons: No Node 26 support
Files Modified for Node 26 Support
GitHub Actions Workflows (5 files)
.github/workflows/main.yml - Updated matrix to [22, 24, 26]
.github/workflows/audit.yml - Updated matrix to [22, 24, 26]
.github/workflows/docs.yml - Updated to Node 26.x
.github/workflows/pre-release.yml - Updated to Node 26.x
.github/workflows/release.yml - Updated to Node 26.x
Root Package Configuration
package.json - Added yargs override to ^18.0.0
Service package.json (16 files)
- All services in
services/ directory - Updated engines to ">=22"
Package package.json (7 files)
- All packages in
packages/ directory - Updated engines to ">=22"
packages/observability/tsconfig.json - Updated moduleResolution to "Node16"
Sandbox package.json (32 files)
- All examples in
sandbox/ directory - Updated engines to ">=22"
CLI Templates (2 files)
packages/cli/src/generators/project/templates/package.json.ejs
packages/cli/src/generators/project/templates/package.plain.json.ejs
Test Commands
# Node version check
node -v # v26.2.0
# Command 1: Installation and build
npm run afterinstall
# Command 2: Build all packages/services
lerna run build
# Command 3: Run all tests
lerna run test
# Command 4: Clean install
rm -rf node_modules package-lock.json
npm ci
Current Node.js Support Status
| Version |
Status |
Notes |
| Node 20 |
❌ Removed |
Support removed as part of this update |
| Node 22 |
✅ Working |
Tested and compatible |
| Node 24 |
✅ Working |
Tested and compatible |
| Node 26 |
❌ BLOCKED |
Issues #2, #3 blocking builds |
Node.js 26 Compatibility Issues Report
Project: loopback4-microservice-catalog
Node Version Tested: 26.2.0
Executive Summary
The project is NOT ready for Node.js 26 due to dependency ecosystem issues. After updating CI workflows and package.json files to support Node 26, testing revealed multiple compatibility issues that prevent successful installation and build.
Root Cause: Node 26 introduced stricter ES module handling and API changes that exposed issues in unmaintained dependencies.
Why Didn't This Happen Before?
Node 22/24 vs Node 26:
The Key Changes:
require()illegal in ES modulesSummary: All Issues Are Dependency-Related
No actual application code changes required (no .ts or .js file changes needed in your source code).
The "code changes" needed are only in:
Why Problems Now? - Detailed Analysis
The Root Cause Chain
Complete Issue List with "Why Now" Analysis
Issue #1: yargs ESM Incompatibility
What is yargs?
A Node.js package for parsing command-line arguments. Used by hundreds of npm packages.
How it worked before (Node 22/24):
Why it breaks now (Node 26):
The Error:
Proper Solution:
Upgrade to yargs@18.x which has proper ES module support.
BUT → This creates new problems (Issues #2 and #3)
Status: 🟡 Partially Fixed (upgraded to 18.x, but created downstream issues)
Error:
Description:
yargs@17.7.2has"type": "module"in package.json but usesrequire()syntax, which is invalid in ES modules with Node 26's stricter enforcement.Fix Applied: Upgraded to
yargs@18.0.0via package.json overrideResult: Fixed yargs itself, but broke dependent packages (see issues #2 and #3).
Issue #2: copyfiles Package - yargs API Incompatibility
Status: 🔴 BLOCKING
What is copyfiles?
A package that copies files in your project. Used by
@sourceloop/clito copy template files.How it worked before (Node 22/24):
Why it breaks now (Node 26 + yargs 18.x):
The API Change:
The Error:
Why copyfiles breaks:
copyfileswas written 3+ years ago and expects the old API. The package is unmaintained - no updates.Affected Package:
@sourceloop/cli@12.2.6build processCode Location:
packages/cli/package.jsonPackage Status:⚠️ Unmaintained (last update 3+ years ago)
Build Command Affected:
npm run afterinstall,lerna run buildProper Solution:
Replace
copyfileswith maintained alternative likecpy.Options:
copyfilesfor yargs 18 compatibilitycpy)Issue #3: widdershins Package - yargs API Incompatibility
Status: 🔴 BLOCKING
What is widdershins?
Converts OpenAPI JSON specs to Markdown documentation for API docs.
How it worked before (Node 22/24):
Why it breaks now (Node 26 + yargs 18.x):
The Error:
Why widdershins breaks:
Same problem as copyfiles - expects yargs 17.x API, package is unmaintained.
Package Status:⚠️ Unmaintained
Build Command Affected:
lerna run build,npm run afterinstallAffected Services (16 total):
@sourceloop/audit-service@sourceloop/authentication-service@sourceloop/bpmn-service@sourceloop/chat-service@sourceloop/in-mail-service@sourceloop/notification-service@sourceloop/oidc-service@sourceloop/payment-service@sourceloop/reporting-service@sourceloop/scheduler-service@sourceloop/search-service@sourceloop/survey-service@sourceloop/task-service@sourceloop/user-tenant-service@sourceloop/video-conferencing-serviceCode Pattern (in each service):
Proper Solution:
Either:
Options:
widdershinsfor yargs 18 compatibilityIssue #4: OpenTelemetry Module Path Issue
Status:
What is this?
TypeScript trying to find
@opentelemetry/semantic-conventions/incubatingmodule.How it worked before (Node 22/24):
Why it breaks now (Node 26):
The Package Export Structure:
Original Error:
The Import:
Affected Package:
@sourceloop/observability@0.0.1Code Location:
packages/observability/src/profiles/otlp.profile.ts:15Fix Applied: Updated
packages/observability/tsconfig.json:{ "compilerOptions": { "moduleResolution": "Node16", "module": "Node16" } }Build Command Affected:
npm run afterinstall,lerna run buildResult:
Note: Node16 moduleResolution properly handles package.exports field.
Issue #5: localStorage Warning
Status:⚠️ WARNING (Non-blocking)
What is this?
Node 26 Web Storage API warning for localStorage.
How it worked before (Node 22/24):
Why warning appears now (Node 26):
The Warning:
Description: Node 26 Web Storage API requires explicit file path for localStorage.
Affected: Services using
node ./dist/openapi-speccommandSeverity: LOW - Warning only, does not block builds
Build Commands Affected:
npm run afterinstall,lerna run buildProper Solution:
Either ignore (warning only) or add
--localstorage-fileflag to Node commands.Issue #6: AWS SDK v2 End-of-Support Warning
Status:⚠️ WARNING (Non-blocking)
What is this?
AWS SDK for JavaScript v2 has reached end-of-support.
How it worked before (Node 22/24):
Why warning appears now (Node 26):
The Warning:
Description: AWS SDK v2 has reached end-of-life.
Severity: LOW - Deprecation warning only
Recommendation: Plan migration to AWS SDK v3
Build Commands Affected: Services using AWS SDK
Proper Solution:
Plan migration to AWS SDK v3 (not urgent).
Issue Status Summary
Dependency Chain Problem
The JavaScript/npm dependency ecosystem creates chains. When yargs upgraded to 18.x for Node 26 compatibility, it broke packages using the old API.
yargs API Changes (17.x → 18.x)
The upgrade from yargs 17 to 18 introduced breaking API changes:
Packages like
copyfilesandwiddershinsneed to be updated to callyargs()as a function first.Resolution Options
Option 1: Replace Dependencies 🔄
Effort: High
copyfiles replacement:
cpy- Active maintenancewiddershins alternatives:
@apidevtools/swagger-parser+ custom markdown generatorredocfor HTML documentationPros: Modern, maintained packages
Cons: Significant code changes required
Option 2: Skip apidocs Generation 📝
Effort: Low
apidocsscript in all affected servicesopenapi-spec(JSON generation works fine)Pros: Unblocks builds immediately
Cons: No markdown documentation
Option 3: Stay on Node 22/24 ✅
Effort: None
Pros: Everything works now
Cons: No Node 26 support
Files Modified for Node 26 Support
GitHub Actions Workflows (5 files)
.github/workflows/main.yml- Updated matrix to [22, 24, 26].github/workflows/audit.yml- Updated matrix to [22, 24, 26].github/workflows/docs.yml- Updated to Node 26.x.github/workflows/pre-release.yml- Updated to Node 26.x.github/workflows/release.yml- Updated to Node 26.xRoot Package Configuration
package.json- Added yargs override to ^18.0.0Service package.json (16 files)
services/directory - Updated engines to ">=22"Package package.json (7 files)
packages/directory - Updated engines to ">=22"packages/observability/tsconfig.json- Updated moduleResolution to "Node16"Sandbox package.json (32 files)
sandbox/directory - Updated engines to ">=22"CLI Templates (2 files)
packages/cli/src/generators/project/templates/package.json.ejspackages/cli/src/generators/project/templates/package.plain.json.ejsTest Commands
Current Node.js Support Status