Troubleshooting
A step-by-step guide to diagnosing issues with your Miren applications and server.
Quick health check
Start with miren doctor to verify your environment is set up correctly:
miren doctor
This checks your configuration, server connectivity, versions, and authentication, and names the command that fixes anything it finds wrong.
Install the Miren agent skills and ask your AI coding agent to
"check the health of this app" or "check the health of this cluster."
The app-health and cluster-health skills combine status, deployment history,
logs, and diagnostics into a prioritized report with suggested next steps.
App not starting
If your app is deployed but not responding:
1. Check the app status
miren app status -a myapp
This shows the current deployment state, version, configuration, and any error messages.
2. Check the logs
# Recent logs
miren logs -a myapp
# Live tail
miren logs -a myapp -f
# Filter for errors
miren logs -a myapp -g error
# Logs from a specific service
miren logs -a myapp --service web
3. Check sandbox state
miren sandbox list
Look for sandboxes that are stuck in pending or not_ready, or that have gone dead. Use --all to include dead sandboxes in the output.
Deploy failed
1. Find the failed deployment
miren app history -a myapp
Failed deployments are marked with a red ✗. Use --detailed for more info including error messages and git SHAs.
2. Check build logs
miren logs build -a myapp VERSION
Replace VERSION with the version from the deployment history. This shows the build output so you can see where things went wrong. See Logs for more on filtering and following logs.
Server-level issues
If you suspect the Miren server itself is having problems:
1. Check server logs on the host
For systemd installations:
sudo journalctl -u miren -f
For container installations (Docker or Podman), use whichever runtime you installed with:
docker logs -f miren # or: podman logs -f miren
Docker's daemon restarts the miren container automatically after a reboot.
Podman is daemonless, so --restart always only covers crashes while the
machine is up — it won't bring the container back after a reboot on its own.
On a systemd host, enable podman-restart.service
(sudo systemctl enable --now podman-restart.service, or the --user variant
plus loginctl enable-linger for a rootless install), or generate a dedicated
unit with podman generate systemd / a Quadlet.
The restart policy is also what miren cluster restart and miren cluster upgrade rely on for a container install: the server exits and the runtime
brings a new container up on the same data volume. miren server container install sets --restart always; a container started some other way without
it will stay down after a restart, and a server that wasn't started through
the image's entrypoint reports install_kind: unknown and refuses restart and
upgrade rather than trying.
2. Test connectivity
miren debug connection
This tests RPC and HTTP connectivity to the server and reports the server version and auth status.
The server restarted on its own
On a systemd install, the Miren server runs under a memory limit. If it ever exceeds that limit, the kernel stops the server and systemd starts it again. That is deliberate: a server that grows without bound would otherwise take the whole machine down, and a machine you can still reach is worth more than a server that never restarts.
Your apps keep running through this. They have their own cgroups — the kernel's per-workload memory accounting — outside the server's, so the limit does not apply to them and the restart doesn't stop them.
When it happens, the server says so the next time it starts:
miren logs system
Look for previous miren server run was killed for exceeding its memory limit.
It carries the memory the server reached, the limit it was held to, and how many
times systemd has restarted it.
Seeing the current limit
systemctl show -p MemoryMax -p MemoryHigh miren
Miren sets this at install time to a quarter of the machine's memory, with a floor of 2 GB, and refreshes it on each upgrade. The limit covers the server process, containerd, and the per-container shims — not your apps or addon databases.
Most of what it covers is cached file data, not the server itself. containerd charges every image layer it reads to this group, so a busy machine can show tens of gigabytes here while the server's own memory is a few hundred megabytes. Cached data is given back automatically when the limit is approached, which is why the limit is a share of the machine rather than a fixed size: it has to leave room for that cache on a large host while still catching a runaway on a small one.
Raising it
A single restart usually means a bug worth reporting. Repeated restarts on a busy cluster can mean the limit is genuinely too low for your workload. Raise it with a systemd override, which takes precedence over the value Miren manages and survives upgrades:
sudo systemctl edit miren
Add:
[Service]
MemoryMax=24G
MemoryHigh=20G
Then sudo systemctl daemon-reload && sudo systemctl restart miren.
systemctl edit is the only place an override survives. A limit written
directly into /etc/systemd/system/miren.service is ignored in favour of the
one Miren manages, because systemd applies drop-in files after the unit file —
so a hand-written limit can be silently replaced by a lower one on the next
upgrade. If you set a limit before upgrading to this version, move it.
Crossing MemoryHigh puts the server under reclaim pressure and slows it down
instead of stopping it. That buys time to notice and act, but it isn't a
recovery: the kernel can reclaim cached file data, not the server's live memory,
so a genuine leak still reaches MemoryMax and is stopped. Setting the two
equal, or leaving MemoryHigh unset, removes even the warning band and the
server goes straight from healthy to stopped.
Gathering a debug bundle
If you've worked through the steps above and need further help, collect a debug bundle to share:
sudo miren debug bundle
This creates a miren-debug.tar.gz archive containing system info, container state, process lists, and server logs.
Debug bundles collect diagnostic data that may include sensitive information:
- Process command lines — arguments passed to running processes may contain tokens or credentials
- Application logs — error messages and stack traces can include request data or internal details
Environment variable values are automatically redacted from container inspect output, but logs and process arguments are included as-is. Review the bundle contents and remove anything sensitive before sharing, especially in public channels like GitHub Issues.
Without sudo, the command still runs but produces a partial bundle. Root access is needed for:
- Containerd socket — the primary source of container state
- System journal — miren server logs via journalctl
- Docker/Podman socket — for Docker, unless your user is in the
dockergroup (rootless Podman needs no group)
Bundle options
| Flag | Description | Default |
|---|---|---|
-o, --output | Output file path | miren-debug.tar.gz |
-s, --since | Include logs since this time | 1 day ago |
-d, --docker-container | Server container name (Docker or Podman) | miren |
# Include logs from the last week
sudo miren debug bundle --since "7 days ago"
# Save to a specific path
sudo miren debug bundle -o /tmp/miren-debug.tar.gz
Getting help
If you're stuck, share your debug bundle and what you've tried:
- Discord — miren.dev/discord for community help and questions
- GitHub Issues — File a bug report and attach your debug bundle
- Feature Requests — Miren Roadmap for ideas and suggestions
Remember to review debug bundles for sensitive data before attaching them to public issues.