Skip to main content

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.

Get a combined diagnosis

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
Podman and restart-on-reboot

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.

Edit the override, not the unit file

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.

Keep MemoryHigh below MemoryMax

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.

Review bundles before sharing

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.

Use sudo for a complete bundle

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 docker group (rootless Podman needs no group)

Bundle options​

FlagDescriptionDefault
-o, --outputOutput file pathmiren-debug.tar.gz
-s, --sinceInclude logs since this time1 day ago
-d, --docker-containerServer 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:

Remember to review debug bundles for sensitive data before attaching them to public issues.