Error: Cannot find module in GitHub Actions: Complete Troubleshooting Guide
DependencyQuick Answer
If a GitHub Actions workflow reports “Error: Cannot find module ‘module-name'”, it means Node.js cannot locate the specified package or file during the CI/CD workflow execution.
Most common causes:
- Missing
npm installornpm cistep in workflow node_modulesnot cached or cache restoration failed- Private npm packages without authentication token
- Path case sensitivity issues (Windows local → Linux runner)
- Lock file not committed or out of sync with package.json
Immediate diagnostic steps:
- name: Debug module resolution
run: |
npm ls <package-name> # Verify package is installed
ls -la node_modules | head -20 # Check node_modules contents
node --trace-resolution index.js # Debug module resolution path
What this error means
According to the Node.js official module resolution documentation, Node.js uses a specific algorithm to locate files when you use require() or import. When this algorithm fails during a GitHub Actions workflow, it throws an error that can be harder to debug than in local development.
Error Message Variants in CI/CD
Depending on your workflow configuration and module system, you may see one of these error formats:
Standard CommonJS Error:
Error: Cannot find module 'express'
Require stack:
- /home/runner/work/my-project/my-project/src/app.js
- /home/runner/work/my-project/my-project/test/app.test.js
ES Modules Error:
Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'lodash' imported from /home/runner/work/my-project/my-project/src/utils.js
GitHub Actions Context Error:
Run npm test
npm test
shell: /usr/bin/bash -e {0}
Error: Cannot find module '@company/private-package'
at Function.Module._resolveFilename (node:internal/modules/cjs/loader.js:xxx)
TypeScript Compilation Error:
Run npx ts-node src/index.ts
Error: Cannot find module '@app/utils'
Require stack:
- /home/runner/work/my-project/my-project/src/index.ts
These errors indicate that despite your workflow configuration, Node’s resolver cannot find the requested module in the GitHub Actions runner environment.
Why this happens
Root Causes Overview
| Cause | Frequency | Complexity |
|---|---|---|
| Missing install step | Very High | Low |
| Cache misconfiguration | High | Medium |
| Private package auth failure | High | Medium |
| Case sensitivity issues | Medium | Medium |
| Lock file out of sync | Medium | Low |
| Monorepo workspace issues | Medium | High |
| Build artifacts missing | Low | Medium |
| Architecture mismatch | Low | High |
The GitHub Actions Environment
GitHub Actions runners are ephemeral Ubuntu (Linux) environments that start fresh for each workflow run. Key characteristics:
- Fresh environment – No
node_modulesfrom previous runs (unless cached) - Linux filesystem – Case-sensitive, unlike Windows/macOS
- No global packages – Unlike your local development machine
- Isolated network – Requires explicit authentication for private resources
Common scenarios
Scenario A: Missing Install Step
Your workflow fails immediately when trying to run tests or build.
# ❌ Wrong - Missing install step
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm test # Error: Cannot find module
Framework-specific examples:
- Express.js API:
Error: Cannot find module 'express' - React/Vue/Angular:
Error: Cannot find module 'react' - Next.js:
Error: Cannot find module 'next' - Jest Testing:
Error: Cannot find module 'jest' - TypeScript:
Error: Cannot find module 'typescript'
Scenario B: Cache Restoration Failure
Your workflow worked before but suddenly fails, or cache hits but modules are still missing.
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm test # Error: Cannot find module
Why it happens:
- Lock file changed but cache key didn’t update
- Cache was corrupted or partially restored
node_modulespartially exists but is incomplete
Scenario C: Private Package Authentication Failure
Error: Cannot find module '@mycompany/private-package'
npm ERR! 404 Not Found - GET https://registry.npmjs.org/@mycompany%2fprivate-package
Why it happens:
NPM_TOKENnot set in repository secrets.npmrcfile not configured for CI- GitHub Packages authentication missing
Common private package scenarios:
@company/shared-utils– Internal utility packages@org/private-sdk– Organization SDKs- GitHub Packages hosted packages
- Artifactory/Nexus private registries
Scenario D: Case Sensitivity Hell
Your code works perfectly on your Windows or macOS machine but fails in GitHub Actions.
// File: src/Components/Button.js
const Button = require('./components/button'); // Wrong case
Why it happens: According to Node.js documentation, module resolution is case-sensitive on Linux (GitHub Actions runners) but case-insensitive on Windows and macOS (by default).
Scenario E: Lock File Out of Sync
npm ERR! `npm ci` can only install packages when your package.json and package-lock.json are in sync.
Why it happens:
package-lock.jsonnot committed to gitnpm installused locally instead ofnpm cipackage.jsonmodified without updating lock file
Scenario F: Monorepo / Workspace Issues
Workspace packages can’t find each other in GitHub Actions.
// In @myorg/package-b
import { helper } from '@myorg/package-a';
// Error: Cannot find module '@myorg/package-a'
Common monorepo tools affected:
- npm Workspaces
- Yarn Workspaces
- pnpm Workspaces
- Turborepo
- Nx
- Lerna
Scenario G: Build Artifacts Missing
Error: Cannot find module '/home/runner/work/my-project/my-project/dist/index.js'
Why it happens:
- TypeScript not compiled before running tests
- Build step skipped or failed silently
- Output directory not preserved between jobs
Scenario H: Job Artifacts Not Passed
Install step succeeds in Job A, but Job B fails with “Cannot find module”.
Why it happens:
- Each job runs on a fresh runner instance
node_modulesnot uploaded as artifact- Jobs don’t share the filesystem
How to fix
Fix A: Add Proper Install Step
Symptoms: Missing node_modules in workflow run.
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
Key points:
- Always use
actions/setup-nodebefore installing - Use
npm ciinstead ofnpm installfor reproducible builds - Place install step before any step that needs dependencies
Fix B: Configure Caching Correctly
Symptoms: Slow installs or cache-related failures.
- name: Setup Node.js with caching
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
For custom cache configuration:
- name: Cache node_modules
uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: Install dependencies
run: npm ci
Fix C: Configure Private Package Authentication
Symptoms: 404 errors for private packages.
For npm private packages:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
registry-url: 'https://registry.npmjs.org'
- name: Install dependencies
run: npm ci
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
Create .npmrc in repository:
//registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}
For GitHub Packages:
- name: Setup Node.js for GitHub Packages
uses: actions/setup-node@v4
with:
node-version: '20'
registry-url: 'https://npm.pkg.github.com'
- name: Install dependencies
run: npm ci
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Fix D: Fix Case Sensitivity Issues
Symptoms: Works locally on Windows/macOS, fails in GitHub Actions.
# Find case mismatches before committing
git ls-files | sort -f | uniq -di
Always use exact casing:
// File is named UserProfile.js
const UserProfile = require('./UserProfile'); // ✅ Correct
const UserProfile = require('./userprofile'); // ❌ Wrong
const UserProfile = require('./userProfile'); // ❌ Wrong
Enable strict case checking in TypeScript:
{
"compilerOptions": {
"forceConsistentCasingInFileNames": true
}
}
Fix E: Ensure Lock File is Committed and Synced
Symptoms: npm ci fails with lock file errors.
# Locally - ensure lock file is up to date
rm -rf node_modules package-lock.json
npm install
# Commit the updated lock file
git add package-lock.json
git commit -m "chore: update lock file"
git push
In workflow:
- name: Install dependencies
run: npm ci # Requires lock file to be in sync
Fix F: Configure Monorepo Workspaces
Symptoms: Workspace packages can’t find each other.
For npm workspaces:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci # Installs all workspace dependencies
- name: Build packages
run: npm run build --workspaces
- name: Run tests
run: npm test --workspaces
For pnpm workspaces:
- name: Setup pnpm
uses: pnpm/action-setup@v2
with:
version: 8
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build
run: pnpm build
Fix G: Ensure Build Artifacts Exist
Symptoms: Cannot find compiled files or dist directory.
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build TypeScript
run: npm run build
- name: Run tests
run: npm test
Upload build artifacts for later jobs:
- name: Build
run: npm run build
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: dist
path: dist/
Fix H: Share Dependencies Between Jobs
Symptoms: Job B fails even though Job A installed dependencies.
jobs:
install:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Upload node_modules
uses: actions/upload-artifact@v4
with:
name: node_modules
path: node_modules/
test:
needs: install
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Download node_modules
uses: actions/download-artifact@v4
with:
name: node_modules
path: node_modules/
- name: Run tests
run: npm test
Checklist
Use this checklist to systematically resolve module errors in GitHub Actions:
- Add
actions/setup-nodestep before installing - Use
npm ciinstead ofnpm install - Verify
package-lock.jsonis committed to git - Configure caching with
cache: 'npm' - Add install step before test/build steps
- Check case sensitivity of import paths
- Configure
NODE_AUTH_TOKENfor private packages - Ensure build step runs before tests (TypeScript)
- Upload/download artifacts between dependent jobs
- Clear cache if experiencing weird behavior
Quick diagnostic workflow:
- name: Debug module resolution
run: |
echo "Node version: $(node --version)"
echo "NPM version: $(npm --version)"
echo "---"
echo "Package.json dependencies:"
cat package.json | grep -A 20 '"dependencies"'
echo "---"
echo "Installed packages:"
npm ls --depth=0 || true
echo "---"
echo "node_modules contents:"
ls -la node_modules | head -20
FAQ
Why does my code work locally but fail in GitHub Actions?
A: Most common reasons:
node_modulesexists locally but isn’t in git (GitHub Actions starts fresh)- Different operating systems (Windows/macOS local → Linux runner)
- Local global packages not available in CI
.envfiles or local configuration not committed- Case sensitivity differences
How do I fix “Cannot find module” for private npm packages?
A:
- Add
NPM_TOKENto repository secrets (Settings > Secrets > Actions) - Configure
actions/setup-nodewith registry URL - Pass token via
NODE_AUTH_TOKENenvironment variable
- uses: actions/setup-node@v4
with:
node-version: '20'
registry-url: 'https://registry.npmjs.org'
- run: npm ci
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
Should I use npm install or npm ci in GitHub Actions?
A: Always use npm ci in CI/CD environments because:
- It’s faster (skips certain user-oriented features)
- It strictly follows
package-lock.jsonfor reproducible builds - It fails if
package.jsonand lock file are out of sync - It deletes existing
node_modulesfor a clean install
Only use npm install if you don’t have a lock file (not recommended).
How do I cache node_modules in GitHub Actions?
A: Use actions/setup-node with built-in caching:
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm' # Automatically caches ~/.npm
Or use actions/cache for more control:
- uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
Why is npm ci failing with lock file errors?
A: npm ci requires package-lock.json to be in sync with package.json. Fix:
# Locally
rm -rf node_modules package-lock.json
npm install
# Commit the updated lock file
git add package-lock.json
git commit -m "fix: update lock file"
git push
How do I handle monorepos in GitHub Actions?
A: For npm workspaces:
- run: npm ci # Installs all workspace dependencies
- run: npm run build --workspaces
- run: npm test --workspaces
For Turborepo with remote caching:
- uses: actions/setup-node@v4
- uses: dtinth/setup-github-actions-caching-for-turbo@v1
- run: npm ci
- run: npx turbo run build test
Can I use different Node.js versions in different jobs?
A: Yes, specify version per job:
jobs:
test-node-18:
runs-on: ubuntu-latest
steps:
- uses: actions/setup-node@v4
with:
node-version: '18'
- run: npm ci
- run: npm test
test-node-20:
runs-on: ubuntu-latest
steps:
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npm test
How do I debug “Cannot find module” in GitHub Actions?
A: Add debug steps to your workflow:
- name: Debug dependencies
run: |
echo "=== Node Version ==="
node --version
echo "=== NPM Version ==="
npm --version
echo "=== Package.json ==="
cat package.json
echo "=== Installed Packages ==="
npm ls || true
echo "=== node_modules ==="
ls -la node_modules/ | head -30
echo "=== Trace Resolution ==="
node --trace-resolution index.js || true
Why are my workspace packages not found in GitHub Actions?
A: Common causes:
- Missing build step for workspace packages
- Incorrect workspace configuration
- Dependencies not hoisted properly
Fix:
- run: npm ci
- run: npm run build --workspaces # Build all packages first
- run: npm test --workspaces
How do I handle native modules (node-gyp) in GitHub Actions?
A: Install build tools before npm install:
- name: Install build tools
run: |
sudo apt-get update
sudo apt-get install -y python3 make g++
- name: Install dependencies
run: npm ci
Or use prebuilt binaries when available:
npm install sharp --platform=linux --arch=x64