TypeScript Module Resolution Issues - Cannot Find Controller Files in Build Environment

kamalcharan
HOBBY

3 months ago

I'm experiencing a critical deployment issue where my Node.js/TypeScript application builds successfully locally but fails on Railway with TypeScript module resolution errors.

Environment:

  • Platform: Railway

  • Runtime: Node.js 18

  • Build Method: Dockerfile

  • Framework: Express.js with TypeScript

  • Build Tool: ts-node

Issue Summary: My application works perfectly in local development (Windows) and local Docker, but consistently fails on Railway with "Cannot find module" errors for controller files that definitely exist.

Error Details:

TSError: ⨯ Unable to compile TypeScript:
src/routes/auth.ts(3,28): error TS2307: Cannot find module '../controllers/authController' or its corresponding type declarations.
src/routes/masterDataRoutes.ts(9,8): error TS2307: Cannot find module '../controllers/masterDataController' or its corresponding type declarations.

File Structure Confirmed Locally:

src/
├── controllers/
│   ├── authController.ts ✓ (exists)
│   ├── masterDataController.ts ✓ (exists)
│   └── [other controllers]
├── routes/
│   ├── auth.ts (imports '../controllers/authController')
│   └── masterDataRoutes.ts (imports '../controllers/masterDataController')

Import Statements:

// src/routes/auth.ts
import authController from '../controllers/authController';

// src/routes/masterDataRoutes.ts  
import { getCategories } from '../controllers/masterDataController';

What Works:

  • Local development (npm run dev)

  • Local Docker build and run

  • TypeScript compilation locally (npx tsc)

  • All file paths and case sensitivity verified

What Fails:

  • Railway deployment with ts-node runtime compilation

  • Only specific controller imports (not all files)

Configuration Files:

package.json:

{
  "scripts": {
    "start": "ts-node src/index.ts",
    "build": "echo 'Skipping TypeScript compilation - using ts-node'"
  },
  "dependencies": {
    "ts-node": "^10.9.2",
    "typescript": "^5.8.3"
  }
}

tsconfig.json:

{
  "compilerOptions": {
    "target": "es2016",
    "module": "commonjs",
    "moduleResolution": "node",
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  }
}

railway.toml:

[build]
builder = "DOCKERFILE"

Troubleshooting Attempted:

  1. Verified file case sensitivity (all lowercase)

  2. Tested different import syntaxes (named vs default)

  3. Confirmed tsconfig.json module resolution settings

  4. Tried both individual and namespace imports

  5. Verified Railway is using Dockerfile build method

  6. Tested with simplified controller files (no circular dependencies)

Questions:

  1. Are there known issues with ts-node module resolution in Railway's container environment?

  2. Could this be related to file deployment or volume mounting during build?

  3. Are there Railway-specific TypeScript or Node.js path resolution quirks?

Expected Behavior: The application should start successfully on Railway, just as it does locally.

Actual Behavior: Application crashes during startup with TypeScript module resolution errors for files that exist.

Request: Please help identify why Railway's ts-node environment cannot resolve these controller modules, despite them working perfectly in identical local Docker environments.

$10 Bounty

2 Replies

Railway
BOT

3 months ago

Hey there! We've found the following might help you get unblocked faster:

If you find the answer from one of these, please let us know by solving the thread!


2 months ago

Quick Fixes:

Method 1: Check your Dockerfile

Ensure your Dockerfile properly copies all files:

FROM node:18
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
CMD ["npm", "start"]

Method 2: Switch from ts-node to tsc compilation

Replace your current approach:

// package.json
{
  "scripts": {
    "start": "node dist/index.js",
    "build": "tsc"
  }
}

Make sure you have build command in docker file:

FROM node:18
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build    # ✅ Build
CMD ["npm", "start"]  # ✅ Star.t

Method 3: Add tsconfig-paths for ts-node (if keeping ts-node)

npm install --save-dev tsconfig-paths

Update tsconfig.json:

{
  "ts-node": {
    "require": ["tsconfig-paths/register"]
  },
  "compilerOptions": {
    "moduleResolution": "node",
    "baseUrl": "./src",
    ...
  }
}

Why this happens:

  • Railway uses Linux containers (case-sensitive) vs your Windows dev environment

  • ts-node has module resolution issues in containerized environments

  • Working directory differences between local Docker and Railway

Best solution:

Pre-compile with tsc instead of runtime compilation with ts-node. This is more reliable for production deployments and what most Railway users end up doing.

The compilation approach eliminates module resolution issues entirely and matches Railway's recommended deployment patterns.