Troubleshooting
The errors you can meet while installing the store, what causes each one, and how to fix it.
For the Full Stack package
Docker is not running
failed to connect to the docker API at unix:///…/docker.sock; check if the path is correct and if the daemon is runningOlder Docker versions say "Cannot connect to the Docker daemon" instead. Either way, the Docker engine is not started.
Open Docker Desktop
Start Docker Desktop and wait until it reports that the engine is running. On Linux, start the service:
sudo systemctl start docker.Check that Docker answers
Terminaldocker infoExpected result: It prints a Server section instead of an error.
Run your start command again
docker compose up --buildfor the full stack, or yourdocker buildanddocker runfor a single app.
A port is already in use
ports are not available: exposing port TCP 0.0.0.0:3030 … bind: address already in use
Error: listen EADDRINUSE: address already in use :::3030The first line comes from Docker, the second from yarn dev. Another program already listens on 3030, 3031 or 8000: often an earlier run of the store, or another project's dev server.
Find what holds the port
On macOS or Linux:
Terminallsof -i :3030On Windows, in PowerShell:
Terminalnetstat -ano | findstr :3030Stop it
Close that program, or stop the earlier run: Ctrl+C in its terminal,
docker compose downin its folder, ordocker stopfor a container you started withdocker run. Then start the store again.Or run the store on other ports
With the full stack in Docker, create a file named
.envin thee-commerce-1folder, next todocker-compose.yml, with the port you need.SITE_PORTmoves the storefront,ADMIN_PORTthe admin andAPI_PORTthe API; the addresses the apps use follow by themselves.e-commerce-1/.envADMIN_PORT=3041Then run the same command again. After a failed start it picks up where it stopped:
Terminaline-commerce-1docker compose up --buildExpected result: The app answers on its new port, here localhost:3041Local.
Without Docker the ports are fixed in the .env files. To move the API there, change PORT in back-end/.env, NEXT_PUBLIC_API_BASE_URL in both frontends and CORS_ORIGIN together: the three must agree. With Docker, use API_PORT instead. For a single app started with docker run, change the number on the left of -p.
The Docker build fails
The first build downloads the base images and every dependency, then builds the images. It stops with "failed to solve" and the step that failed when something gets in the way.
- No connection or a timeout: the build needs internet access. Run the command again once you are online; finished steps are cached.
- No space left on device: free space in Docker Desktop, or check what Docker uses with
docker system df. - It fails at the same step every time: rebuild without the cache, then start.
e-commerce-1docker compose build --no-cache
docker compose upFor a single-app package, add --no-cache to your docker build command.
A first start that seems stuck is usually still seeding the demo store. The storefront and the admin start only once the API reports itself healthy.
Yarn says its version is 1.22
This project's package.json defines "packageManager": "yarn@4…". However the current global version of Yarn is 1.22…Each app pins Yarn 4 through Corepack. This message means Corepack is not enabled yet, so the old global Yarn answered instead.
corepack enableThen run yarn install again. If your Node.js has no Corepack, install it first with npm install -g corepack.
The API stops before starting
✖ The API cannot start: JWT_SECRET is not set. Set it in back-end/.env to the output of: …
✖ The API cannot start: JWT_SECRET is still the example value from .env.example, …
✖ The API cannot start: CORS_ORIGIN is not set. List the storefront and admin dashboard origins, …The API checks its settings before it starts and prints one line per problem. The causes:
- There is no `.env` file, or `JWT_SECRET` is empty. Create the file in
back-end/withcp .env.example .env. - `JWT_SECRET` is still the example value with `NODE_ENV=production`. Anyone could sign a token with the public example, so a production start refuses it. Generate your own secret.
- `CORS_ORIGIN` is empty with `NODE_ENV=production`. List the storefront's and the admin's addresses, comma separated.
Generate a secret with:
node -e "console.log(require('crypto').randomBytes(48).toString('hex'))"With Docker you do not need one: a container without a JWT_SECRET of its own, or with the example one, generates a secret and keeps it in the data volume.
The health check answers 503
{"status":"unavailable"}
The database has no tables yet. Run `yarn seed` in back-end/, then restart the API./api/health answers 503 until the database answers and holds its tables. The second line is what the API's log says at start-up when the tables are missing.
- Without Docker, in development: run
yarn seedinback-end/(tables and demo store), oryarn db:sync(tables only), then restart the API. - With `NODE_ENV=production`: the API does not create tables on start. Run
yarn db:sync:prod(empty tables) oryarn seed:prod(with the demo store) once, afteryarn build. - With Docker on SQLite: the container creates the database by itself on first start. On MySQL it does not: run the schema or seed command once yourself.
- "The database has no accounts, so nobody can sign in" means the tables exist but no account was ever added: run
yarn seedinback-end/.
MySQL refuses to start or to seed
The API creates its tables in a database that already exists; it does not create the database itself. Create an empty database first, give its name to DB_DATABASE in back-end/.env, then run yarn seed (or yarn db:sync for the tables with no demo store).
- Check the five
DB_*connection values and thatDB_TYPE=mysql. - With
NODE_ENV=productionthe running API never creates tables, so one of those commands has to run before the first start.
Sign-in fails
- Check the account and the app. Staff accounts sign in to the admin at port
3031:admin@example.comwithAdmin@123. Customers sign in to the storefront at port3030:john.doe@example.comwithpassword123. - Check the API's log. "The database has no accounts, so nobody can sign in" means the demo store was never added. Without Docker, run
yarn seedinback-end/. With Docker, the volume was created withSEED_DEMO_DATA=false. - "The database has no tables yet" means the schema was never created: run
yarn seedinback-end/and restart the API. - You changed the Super Admin's password and no longer have it: start over with fresh demo data, below.
- "That email and password combination didn't work. Please try again." is the one answer for an unknown email and for a wrong password alike, so check both.
- "Too many attempts. Wait a minute and try again." means one address made more than 10 tries on a sign-in or password route within a minute. Wait a minute and try again.
Sign-in fails
- Check the API's log. "The database has no accounts, so nobody can sign in" means the demo store was never added: run
yarn seed, or start the Docker container with-e SEED_DEMO_DATA=trueon a new volume. - "The database has no tables yet" means the schema was never created: run
yarn seedand restart the API. - Check the account and the route. Staff sign in at
POST /api/auth/login(the Super Admin isadmin@example.comwithAdmin@123); customers atPOST /api/auth/customer/login(john.doe@example.comwithpassword123). A failed sign-in answers401with the same message whether the email or the password is wrong. - A `429` answer means one address made more than 10 tries on a sign-in, registration, password or order-tracking route within a minute. The
Retry-Afterheader says how many seconds to wait.
Sign-in fails
On the sample store, any email and password sign you in to the storefront, and any valid email with a password of at least 6 characters to the dashboard. Once you connect an API, sign in with an account that exists in it: the demo Super Admin is admin@example.com with Admin@123, and the demo customer john.doe@example.com with password123.
Every visitor gets "Too many attempts" behind a proxy
Sign-in, registration, password reset and guest order tracking allow 10 requests a minute per address and route, then answer 429. The fitting room counts per address too. The API finds the visitor's address in X-Forwarded-For only when the request comes from a proxy on a private, loopback or platform address, as on Railway or behind Caddy or nginx on the same machine.
When your proxy reaches the API from a public address, every visitor looks like that one proxy and they share one allowance. Tell the API how many proxies stand in front of it:
TRUST_PROXY=1TRUST_PROXY=false never reads the header. Leave it unset when the API is reached directly or through a proxy on a private address. The counts live in the API's memory, so a restart clears them.
A "Sample data" notice appears
The frontend is running on its built-in sample store instead of the API, because it was started or built without NEXT_PUBLIC_API_BASE_URL. What you change is then kept in the browser, not in the database, and no order is charged.
Give the frontend the API's address
Create the frontend's
.envfrom.env.exampleif it has none.NEXT_PUBLIC_API_BASE_URLmust be the API's address including/api, for examplehttp://localhost:8000/api.Check that the API answers
Open localhost:8000/api/healthLocal. It should answer
{"status":"ok"}. If the address is set but the API does not answer, the pages cannot load their data: the sample store does not stand in for it.Restart or rebuild the frontend
The address is compiled in. Restart
yarn devafter changing it, runyarn buildagain beforeyarn start, or with Docker rundocker compose up --buildagain.
A change to a frontend's .env does nothing
Every NEXT_PUBLIC_* value is compiled into the JavaScript the browser loads when the app is built. Changing the file changes nothing until the app is built again.
| How you run it | After changing a value |
|---|---|
yarn dev | Stop it and run yarn dev again. |
yarn build and yarn start | Run yarn build again, then yarn start. |
| Docker Compose | Run docker compose up --build. Set the value in the .env next to docker-compose.yml, not in the app's folder. |
docker build for one app | Build the image again with the value as a --build-arg. |
A feature says it is not set up
Card payments, uploads, the AI assistant, the AI studio, background removal and the fitting room switch on only when their keys are in back-end/.env. The fitting room, the studio and background removal also need the media bucket. A key still holding its exact .env.example value counts as not set, so a copied .env.example starts cleanly and each of those features reports itself off instead of failing on its first call.
- Paste your real key over the example value, not next to it.
- Restart the API after changing
back-end/.env. With Docker Compose the API reads that file too, sodocker compose upagain is enough; a single API container needs--env-file .envon itsdocker run.
Uploads answer 503
File uploads are not set up yet. Add the R2 storage settings to the server's .env file to enable them.Every upload from the dashboard (product photos, avatars, chat attachments, the AI studio's results) goes to a Cloudflare R2 or other S3-compatible bucket, and answers 503 until all five R2_* variables are set in back-end/.env. The fitting room, the studio and background removal need the bucket too, and stay off without it. The demo store needs no bucket: its pictures are served from copies both frontends ship in public/mock-media/.
Uploaded images load slowly or at full size
The frontends resize and compress images only from hosts they were built to trust. An image from your bucket on any other host is still shown, but unoptimised.
Name your bucket's public host
Without Docker, set
NEXT_PUBLIC_MEDIA_HOSTNAMEin each frontend's.envto the host ofR2_PUBLIC_URL, for examplepub-1234.r2.dev. With Docker Compose, putMEDIA_HOSTNAME=pub-1234.r2.devin a.envfile next todocker-compose.yml. Write the host only, withouthttps://or a trailing slash.Rebuild the frontends
The host is compiled in. Restart
yarn devand rebuild for production, or rundocker compose up --buildagain.
Requests are blocked on your own domains
Access to fetch at 'https://api.your-domain.com/api/…' from origin 'https://shop.your-domain.com' has been blocked by CORS policyThe API answers browsers only from the addresses in CORS_ORIGIN, and the admin's live notifications only from FRONTEND_URL. Both default to the two local ports, so on your own domains they must name your sites.
CORS_ORIGIN=https://shop.your-domain.com,https://admin.your-domain.com
FRONTEND_URL=https://admin.your-domain.comWrite each address exactly as the browser shows it, with https:// and without a trailing slash, then restart the API. With Docker Compose, set SITE_URL, ADMIN_URL and API_URL in the .env next to docker-compose.yml instead and run docker compose up --build: the compose file builds both lists from them.
The API container cannot find its entrypoint
exec /usr/local/bin/docker-entrypoint.sh: no such file or directoryThe script has Windows line endings, which an editor or Git on Windows can add. The shipped back-end/Dockerfile strips them while it builds, so this appears only with an image built from a changed Dockerfile. Keep its sed -i 's/\r$//' line, or save the script with LF line endings, then rebuild without the cache.
e-commerce-1docker compose build --no-cache api
docker compose upThe folder looks different
Run the commands inside the folder the ZIP extracts to. If the unzip command is missing, extract it with your file manager instead; some tools add an extra folder named after the ZIP, so move into the inner one.
| Package | Folder | Contains |
|---|---|---|
| Full Stack | e-commerce-1 | admin-dashboard, back-end, storefront, docker-compose.yml |
| Storefront | storefront | Dockerfile, package.json, .env.example |
| Admin Dashboard | admin-dashboard | Dockerfile, package.json, .env.example |
| Backend API | back-end | Dockerfile, package.json, .env.example |
Start over with fresh demo data
This deletes your data
Everything you created locally is removed, and the demo store is seeded again.
With Docker Compose, from the e-commerce-1 folder:
e-commerce-1docker compose down -v
docker compose upWith a single API container, remove the container first (docker ps -a lists it, docker rm -f with its id removes it), then delete the volume and run it again:
back-enddocker volume rm ecommerce-data
docker run -p 8000:8000 -v ecommerce-data:/data -e SEED_DEMO_DATA=true ecommerce-apiWithout Docker, stop the API, then:
back-endrm -f database.sqlite* && yarn seedIn PowerShell:
back-endRemove-Item database.sqlite*; yarn seedRunning yarn seed again on a database you keep is not a reset: it adds only what is missing and never resets a value you changed in the dashboard. On MySQL, yarn db:reset drops every table before yarn seed.
Start over on the sample store
Without an API, your changes are kept in the browser. To bring the sample store back, run this in the browser's console on the app's page:
localStorage.removeItem("mock_db_v1"); location.reload();