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

7 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:

  • white_check_mark emoji Local development (npm run dev)

  • white_check_mark emoji Local Docker build and run

  • white_check_mark emoji TypeScript compilation locally (npx tsc)

  • white_check_mark emoji All file paths and case sensitivity verified

What Fails:

  • x emoji Railway deployment with ts-node runtime compilation

  • x emoji 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. white_check_mark emoji Verified file case sensitivity (all lowercase)

  2. white_check_mark emoji Tested different import syntaxes (named vs default)

  3. white_check_mark emoji Confirmed tsconfig.json module resolution settings

  4. white_check_mark emoji Tried both individual and namespace imports

  5. white_check_mark emoji Verified Railway is using Dockerfile build method

  6. white_check_mark emoji 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

7 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!


7 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.


Loading...