---
title: Troubleshooting
description: Solutions to the most common Sencho setup and runtime problems.
---

## Containers won't start after deploy

**Symptom:** You click Deploy and containers immediately exit or never appear.

**Check:** Open the [Host Console](/features/host-console) and run:

```bash
docker compose -f /path/to/your/stack/compose.yaml logs
```

The most common causes:

- **Missing environment variable** - a required variable in your `.env` file is empty or has the wrong name.
- **Port already in use** - another container or host process is bound to the same port. Change the host port in the compose file.
- **Volume path does not exist** - a bind-mount path on the host doesn't exist yet. Create the directory manually.

---

## The 1:1 path rule - volumes resolve to wrong paths

**Symptom:** Stacks deploy but relative volume paths (e.g. `./config:/config`) point to the wrong location inside the container, or `docker compose` exits with a path error.

**Cause:** Your `COMPOSE_DIR` is mounted at a different path inside the Sencho container than it has on the host.

**Fix:** Your compose volume mount and `COMPOSE_DIR` environment variable must use the **same absolute path** on both sides:

```yaml
# docker-compose.yml for Sencho itself
volumes:
  - /opt/docker:/opt/docker        # same path inside and outside
environment:
  - COMPOSE_DIR=/opt/docker
```

See [Configuration - the 1:1 path rule](/getting-started/configuration#compose-directory-the-11-path-rule) for a full explanation.

---

## "Permission denied" on the Docker socket

**Symptom:** Sencho starts but shows errors accessing Docker, or the stack list is empty even though containers exist.

**Cause:** The Sencho container cannot read `/var/run/docker.sock`.

**Fix:** Ensure the socket is mounted:

```yaml
volumes:
  - /var/run/docker.sock:/var/run/docker.sock
```

On Linux, the Docker socket is owned by the `docker` group. The Sencho entrypoint detects the socket's GID automatically and adds the internal `sencho` user to the matching group. If you see permission errors despite a correct mount, check that the socket file is readable:

```bash
ls -la /var/run/docker.sock
# Expected: srw-rw---- 1 root docker ...
```

If the group is not `docker`, the auto-detection still works - Sencho reads the GID from the socket file at startup.

---

## "Permission denied" when deleting a stack

**Symptom:** Clicking Delete on a stack fails with a permission error mentioning `EACCES`.

**Cause:** Stack directories often contain files owned by root — for example when Docker Compose was run with `sudo`, or when containers write config/data files into the stack directory. Since Sencho runs as a non-root user, the OS denies the removal.

This is especially common when installing Sencho on a server where stacks were originally created outside of Sencho (e.g. via `sudo docker compose up`). Those directories and their contents are root-owned, but Sencho can still delete them.

**How Sencho handles it:** Sencho automatically detects permission errors during deletion and falls back to a Docker-based cleanup. It spawns a short-lived Alpine container that bind-mounts the stack directory and removes the root-owned files. This happens transparently — no manual intervention is needed in the standard Docker setup.

**If automatic cleanup fails:** The error message will include the directory path. Remove it manually:

```bash
sudo rm -rf /path/to/your/compose/dir/stack-name
```

**Prerequisites:** The Docker socket must be mounted (standard setup). If Sencho cannot access Docker, the fallback will not work — see [Permission denied on the Docker socket](#permission-denied-on-the-docker-socket).

---

## Login page shows "Something went wrong"

**Symptom:** You enter credentials and get a generic error instead of being logged in.

**Possible causes and fixes:**

| Cause | Fix |
|-------|-----|
| `JWT_SECRET` is not set or is empty | Set a non-empty value for `JWT_SECRET` in your environment |
| Container restarted and session cookie is stale | Clear browser cookies for the Sencho domain and try again |
| Rate limit triggered (5 failed attempts in 15 min) | Wait 15 minutes, or restart the container to reset the limiter |

---

## WebSocket connections fail (logs/console not streaming)

**Symptom:** The log viewer or host console shows a spinner that never resolves, or you see "Disconnected" immediately after connecting.

**Cause:** A reverse proxy is not forwarding WebSocket upgrade headers.

**Fix:** Add WebSocket support to your proxy config:

```nginx
# Nginx
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600s;
```

Traefik handles WebSocket upgrades automatically for HTTP/1.1 backends - no extra config needed.

---

## Remote node shows "Offline" or "Unknown"

**Symptom:** A node you added shows a red or gray status dot.

**Checks in order:**

1. **Is the remote Sencho instance running?** SSH to that machine and verify.
2. **Is the API URL correct?** It must include the protocol and port (e.g. `http://192.168.1.20:3001`). Open it in a browser - you should see a JSON response from `/api/health`.
3. **Is the token correct?** Tokens are long JWT strings. Even one missing character will cause auth to fail. Regenerate the token on the remote instance and update the node config.
4. **Is there a firewall blocking the port?** The primary Sencho host must be able to reach the remote host's Sencho port.

Click the **wifi icon** on the node row to re-test connectivity after making changes.

---

## Pro features return 403 on remote nodes

**Symptom:** A Pro or Admiral feature works on the local node but returns "This feature requires Sencho Pro" (403) when you switch to a remote node.

**Checks in order:**

1. **Is your primary instance licensed?** Go to **Settings > License** on the primary instance and verify it shows an active Skipper or Admiral license. Remote nodes inherit the primary's tier — if the primary is on Community, all remote nodes will be Community too.
2. **Is the remote node's token valid?** An expired or revoked token prevents the license tier from being transmitted. Regenerate the token on the remote instance and update the node config on the primary.
3. **Is the remote node running an up-to-date version of Sencho?** Distributed license enforcement requires both the primary and remote instances to be on v0.34.0 or later. Update the remote node if it's on an older version.
4. **Are you accessing the remote node directly?** If you navigate directly to the remote Sencho instance's URL (bypassing the primary), it uses its own local license. License inheritance only works through the primary's proxy.

---

## Forgotten admin password

Sencho has no password recovery flow. To reset the password:

1. Stop the Sencho container
2. Connect to the SQLite database directly:

```bash
sqlite3 /path/to/data/sencho.db
```

3. Delete the existing credentials so Sencho re-enters first-boot setup mode:

```sql
DELETE FROM global_settings WHERE key IN ('auth_username', 'auth_password_hash', 'auth_jwt_secret');
```

4. Restart the container - the setup screen will appear on next visit.

<Warning>
  This resets authentication entirely. All active sessions become invalid. Your stacks, nodes, and alert rules are not affected.
</Warning>

---

## Scan stacks folder doesn't find my stacks

**Symptom:** You placed Docker Compose files in the stacks directory and clicked the scan button, but "No new stacks found" appears.

**Checks in order:**

1. **Is the compose file in a subdirectory?** Sencho only discovers stacks inside subdirectories of `COMPOSE_DIR`. A loose `compose.yaml` sitting directly in the root of `COMPOSE_DIR` is ignored — each stack must be in its own folder (e.g. `COMPOSE_DIR/my-app/compose.yaml`).

2. **Is the compose file named correctly?** Sencho recognizes these filenames only:
   - `compose.yaml`
   - `compose.yml`
   - `docker-compose.yaml`
   - `docker-compose.yml`

   Other names (e.g. `docker-compose.prod.yaml`, `stack.yaml`) are not detected.

3. **Is the directory empty or missing a compose file?** A subdirectory that exists but contains no recognized compose file will not appear. Add a valid compose file to the directory.

4. **Is the stack already tracked?** Stacks that already appear in the sidebar are not reported again. The scan only reports *changes* since the last time the list was loaded.

---

## Network creation fails with "name is required"

**Symptom:** Clicking Create in the Create Network dialog returns an error about a missing name.

**Cause:** The network name field was left empty or contains only whitespace.

**Fix:** Enter a valid network name. Names must be non-empty and can contain letters, numbers, hyphens (`-`), underscores (`_`), and dots (`.`). Names cannot start with a dot or hyphen.

---

## Network creation fails with "invalid name"

**Symptom:** You enter a network name but the API rejects it as invalid.

**Cause:** The name contains characters that are not allowed, or starts with a special character.

**Allowed characters:** Letters, numbers, hyphens, underscores, and dots. The name must start with a letter, number, or underscore.

**Examples:**

| Name | Valid? | Reason |
|------|--------|--------|
| `my-network` | Yes | |
| `app_net.v2` | Yes | |
| `.hidden` | No | Cannot start with a dot |
| `-leading` | No | Cannot start with a hyphen |
| `my network` | No | Spaces not allowed |
| `net/work` | No | Slashes not allowed |

---

## Cannot delete a system network (bridge, host, none)

**Symptom:** The delete button is missing or disabled for certain networks.

**Expected behavior:** Docker system networks (`bridge`, `host`, `none`) cannot be deleted — they are created by the Docker daemon and are required for normal operation. Sencho intentionally hides the delete action for these networks.

If you need to clean up unused *user-created* networks, use the **Prune Networks** button at the top of the Networks tab.

---

## Network inspect shows "Network not found"

**Symptom:** Clicking the inspect (eye) icon on a network row returns a "not found" error.

**Cause:** The network was deleted between the time the list loaded and when you clicked inspect. This can happen if another user or an external tool removed the network.

**Fix:** Refresh the Resources page to reload the current network list.

---

## Network topology is empty

**Symptom:** The Topology tab shows "No user-created networks found" even though you have running containers.

**Possible causes:**

- **All containers are on system networks only.** The topology view excludes Docker's built-in `bridge`, `host`, and `none` networks. If your containers only use the default bridge, they won't appear. Create a custom network in your compose file to see them in the topology.
- **No containers are connected.** Networks with zero connected containers still appear as nodes, but if you have no user-created networks at all, the view will be empty.

**Fix:** Define custom networks in your compose files:

```yaml
networks:
  frontend:
  backend:

services:
  web:
    networks: [frontend, backend]
  api:
    networks: [backend]
```

After deploying, the topology will show these networks and their connected containers.

---

## Checking the health endpoint

Sencho exposes a health endpoint for monitoring and container health checks:

```bash
curl http://localhost:3000/api/health
# {"status":"ok","uptime":12345.67}
```

A `200` response confirms the backend is running. Use this endpoint in your uptime monitor or load balancer health check.

---

## Getting logs from the Sencho container itself

```bash
docker logs sencho
# or, to follow:
docker logs -f sencho
```

The backend logs all route errors and service failures to stdout. This is the first place to look when the UI shows an error with no useful message.

## "Open App" doesn't appear in the context menu

**Symptom:** You right-click a stack in the sidebar but "Open App" is not listed.

**Cause:** The **Open App** option only appears when both conditions are met:

1. The stack is **running** (status shows UP).
2. At least one container in the stack has a **published port** (a port mapped to the host).

If your container uses host networking, doesn't expose ports, or only binds to internal Docker networks, the option won't appear. You can still access the app manually by checking the container's port mappings in the stack detail view.

## "Check for updates" shows rate-limit error

**Symptom:** Clicking "Check for updates" shows a toast error about waiting before refreshing.

**Cause:** Manual update checks are rate-limited to prevent excessive requests to container registries. Wait for the cooldown period to elapse before checking again. Automatic background checks run every 6 hours regardless of this limit.
