npm error code EUSAGE
chris-opendata
HOBBYOP

2 months ago

I have a Next.js and Node.js project with the following structure on GitHub:

root/

|-->packages

| |-->frontend

| | |-->package.json

| | |-->package-lock.json

| |

| |-->backend

| | |-->package.json

|

|-->package.json

|-->package-lock.json

I tried to deploy it from GitHub, but got the error (see attachment).

I found a similar issue (https://station.railway.com/questions/npm-ci-error-when-attempting-to-build-af-43fc7a56), but the solution there didn't solve my problem.

Can anyone shed some light on solutions?

Thanks

Attachments

Solved$10 Bounty

Pinned Solution

chris-opendata
HOBBYOP

2 months ago

Thanks, darseen and domehane,

I now have toml files updated following your suggestions. Additionally, I switched NIXPACKS to RAILPACK and added "npm ci " into buildCommand. NIXPACKS always ignores the setting and runs "npm ci" in frontend/backend folders. So, it can't be used for shared modules structured like mine. I share the toml files below for anyone facing the same issue. Much appreciated your help.

packages\backend\railway.toml:

[build]

# Tells Railway use RAILPACK instead of an existing Dockerfile.

builder = "RAILPACK"

# We define the root relative to where the command is run

root = "/"

# This builds the TS code and THEN runs migrations

buildCommand = "npm ci && npm run backend:build"

[deploy]

port = 5000

preDeployCommand = "npm run backend:migrate && npm run backend:seed"

startCommand = "npm run backend:start"

healthcheckPath = "/health" # Ensure you have a GET /health route

restartPolicyType = "ON_FAILURE"

# This ensures Railway waits for the app to be 'ready' before routing traffic

healthcheckTimeout = 100

#maxRestarts = 5

[node]

nodeVersion = "20"

packageManager = "npm"

# This ensures only backend changes trigger a redeploy

[service]

watchPaths = [

"packages/backend/**",

"package.json",

"package-lock.json"

]

packages\frontend\railway.toml:

[build]

# Tells Railway use RAILPACK instead of an existing Dockerfile.

builder = "RAILPACK"

root = "/"

# You can explicitly set the build command if it differs from 'npm run build'

buildCommand = "npm ci && npm run frontend:build"

[deploy]

startCommand = "nnpm start -w packages/frontend"

healthcheckPath = "/health"

restartPolicyType = "ALWAYS"

[node]

# Ensures we use a modern Node version

nodeVersion = "20"

# This prevents the frontend from rebuilding when you only update backend logic

[service]

watchPaths = [

"packages/frontend/**",

"package.json",

"package-lock.json"

]

7 Replies

domehane
FREETop 10% Contributor

2 months ago

your backend folder is missing a package-lock.json (frontend has one but backend doesn't)

run thid:

cd packages/backend
npm install

commit the package-lock.json it creates and redeploy


domehane

your backend folder is missing a package-lock.json (frontend has one but backend doesn't)run thid:cd packages/backend npm installcommit the package-lock.json it creates and redeploy

chris-opendata
HOBBYOP

2 months ago

Thanks for your reply. Both the frontend and the backend share what installed in the root, while the frontend also installed a few client / UI specific modules under its folder. That is how the project is set up for module sharing. It worked very well on GitHub with workflow to deploy to the other platform. So, it seems that the Railway automated deployment process has limited capacity to handle various deployment scenarios. I'm wondering there is a way to use a customized workflow to deploy to Railway.


domehane
FREETop 10% Contributor

2 months ago

hey, just want to confirm a few things ; did you set a root directory in your railway service settings? also what's inside your packages/backend/railway.toml file? and is your root package-lock.json actually committed to git?


domehane

hey, just want to confirm a few things ; did you set a root directory in your railway service settings? also what's inside your packages/backend/railway.toml file? and is your root package-lock.json actually committed to git?

chris-opendata
HOBBYOP

2 months ago

Thank you for your prompt reply. What I did was to authorize Railway to my GitHub repository, then the Railway automatically linked to the frontend and backend in the Dashboard. I clicked "Deploy" thereafter. My assumption was that the Railway had already figured out the root, frontend, and backend folders by itself because it would not link the frontend and backend correctly on the Dashboard. So, in short, I haven't touched service settings yet in this case.

Here is the backend toml:

"

[build]

# Tells Railway use Nixpacks instead of an existing Dockerfile.

builder = "NIXPACKS"

# We define the root relative to where the command is run

root = "packages/backend"

# This builds the TS code and THEN runs migrations

buildCommand = "npm install && npm run build && npm run migration:run"

[deploy]

port = 5000

startCommand = "npm run start"

healthcheckPath = "/health" # Ensure you have a GET /health route

restartPolicyType = "ON_FAILURE"

# This ensures Railway waits for the app to be 'ready' before routing traffic

healthcheckTimeout = 100

"

and the frontend toml

"

[build]

# Tells Railway use Nixpacks instead of an existing Dockerfile.

builder = "NIXPACKS"

root = "packages/frontend"

# You can explicitly set the build command if it differs from 'npm run build'

buildCommand = "npm run build"

[deploy]

startCommand = "npm run start"

healthcheckPath = "/health"

restartPolicyType = "ALWAYS"

[node]

# Ensures we use a modern Node version

nodeVersion = "20"

"

Another thing I noticed is that removing a failed deployment seemed to wipe out variables previously set.

Anyway, this is my second day of using the Railway platform. It hasn't been a seamless experience. But, I appreciate enlightenment from experienced community members like you. I'm looking forward to any suggestions.

P.S. Let me also share the package.json in the project root to help understand how the project is packaged, built, and run:

"

{

"name": "my-monorepo",

"version": "1.0.0",

"description": "My monorepo containing frontend and backend packages",

"private": true,

"workspaces": [

"packages/*"

],

"scripts": {

"dev": "concurrently \"npm run dev -w packages/backend\" \"npm run dev -w packages/frontend\"",

"build": "npm run build --workspaces",

"test": "npm run test --workspaces",

"lint": "npm run lint --workspaces",

"lint:fix": "npm run lint:fix --workspaces",

"typecheck": "npm run typecheck --workspaces",

"format": "npm run format --workspaces",

"format:check": "npm run format:check --workspaces",

"backend:dev": "npm run dev -w packages/backend",

"frontend:dev": "npm run dev -w packages/frontend",

"backend:build": "npm run build -w packages/backend",

"backend:start": "npm run start -w packages/backend",

"frontend:build": "npm run build -w packages/frontend"

},

"devDependencies": {

"concurrently": "^8.2.0"

},

"dependencies": {

"pdf-lib": "^1.17.1"

}

}

"


domehane
FREETop 10% Contributor

2 months ago

i think the issue is root = "packages/backend" in your railway.toml , that's why npm ci can't find the package-lock.json (it only exists at root level)


darseen
HOBBYTop 5% Contributor

2 months ago

I host a monorepo with multiple apps on railway using turborepo and pnpm, so I hope I can help.

First, you need to setup your service manually, link it to your github repo and leave root directory empty or set it to / .
You already have your scripts ready, so you can use them in your service settings like this:

For your backend service:

Root directory: empty or /
Build command: npm run backend:build
Start command: npm run backend:start

I recommend setting Watch Paths to packages/backend/** , you can add more watch paths as needed of course. This is to help build your backend service only when the specified watch paths change.

For your forntend service:

Root directory: empty or /
Build command: npm run frontend:build
Start command: npm start -w packages/frontend (since I don't see "frontend:start" in your package.json)

This way, you install all packages using npm ci from root, and build/launch your apps from root as well.

Hope this helps. And if you have any other problems, don't hesitate to tell us.


chris-opendata
HOBBYOP

2 months ago

Thanks, darseen and domehane,

I now have toml files updated following your suggestions. Additionally, I switched NIXPACKS to RAILPACK and added "npm ci " into buildCommand. NIXPACKS always ignores the setting and runs "npm ci" in frontend/backend folders. So, it can't be used for shared modules structured like mine. I share the toml files below for anyone facing the same issue. Much appreciated your help.

packages\backend\railway.toml:

[build]

# Tells Railway use RAILPACK instead of an existing Dockerfile.

builder = "RAILPACK"

# We define the root relative to where the command is run

root = "/"

# This builds the TS code and THEN runs migrations

buildCommand = "npm ci && npm run backend:build"

[deploy]

port = 5000

preDeployCommand = "npm run backend:migrate && npm run backend:seed"

startCommand = "npm run backend:start"

healthcheckPath = "/health" # Ensure you have a GET /health route

restartPolicyType = "ON_FAILURE"

# This ensures Railway waits for the app to be 'ready' before routing traffic

healthcheckTimeout = 100

#maxRestarts = 5

[node]

nodeVersion = "20"

packageManager = "npm"

# This ensures only backend changes trigger a redeploy

[service]

watchPaths = [

"packages/backend/**",

"package.json",

"package-lock.json"

]

packages\frontend\railway.toml:

[build]

# Tells Railway use RAILPACK instead of an existing Dockerfile.

builder = "RAILPACK"

root = "/"

# You can explicitly set the build command if it differs from 'npm run build'

buildCommand = "npm ci && npm run frontend:build"

[deploy]

startCommand = "nnpm start -w packages/frontend"

healthcheckPath = "/health"

restartPolicyType = "ALWAYS"

[node]

# Ensures we use a modern Node version

nodeVersion = "20"

# This prevents the frontend from rebuilding when you only update backend logic

[service]

watchPaths = [

"packages/frontend/**",

"package.json",

"package-lock.json"

]


Status changed to Solved brody 2 months ago


Loading...