Back to Blog
HermesDockerTroubleshootingSelf-Hosting

Hermes Agent Docker Container Keeps Restarting: A Fix Guide

Diagnose why your Hermes Agent Docker container keeps restarting. OOM kills, bad .env, volume permissions, port conflicts, and ARM image mismatches.

By Hermify Team||7 min read
A dark terminal showing a Hermes Agent Docker container in a restart loop, with green highlights on the exit code

Your Hermes Agent container starts, dies within seconds, and Docker keeps bringing it back. docker ps shows a Restarting (137) 3 seconds ago line, the bot never answers on Telegram, and hermes logs scrolls the same startup banner over and over. That loop is almost always one of five very specific problems, and the exit code Docker prints tells you which one. This post walks each of them down in the order that fixes the most agents.

If you have not run the container before, start with how to run Hermes Agent in Docker first. This guide assumes the image pulls fine, the compose file is in place, and something goes wrong the moment the process starts.

Step 1 - Read the actual exit code before you change anything

Docker exposes the exit code of the last run inside the container state. Read it directly instead of guessing from the logs:

docker inspect --format='{{.State.ExitCode}} OOM={{.State.OOMKilled}} err={{.State.Error}}' hermes-agent

That single line tells you three things at once: the exit code, whether the kernel OOM killer ended the process, and any daemon-level error Docker attached to the run. The exit code narrows the search space dramatically:

  • 137 - the process was sent SIGKILL. Almost always an OOM kill from a container memory limit or the host running out of RAM, occasionally a docker stop that hit its 10-second grace timeout.
  • 139 - segmentation fault. On Hermes Agent this shows up when the image architecture does not match the host (an amd64 image on an ARM VPS, or the reverse).
  • 125 / 126 / 127 - Docker itself could not run the container. 125 means the daemon rejected the run (bad options, missing image). 126 means the entrypoint exists but is not executable. 127 means the entrypoint path is wrong or the shell it needs is missing.
  • 1 or 2 - the Hermes Agent process started and exited with an application error. Read docker logs hermes-agent --tail 100 and look for the first line that is not a startup banner.

Only when you know which of these you have does it make sense to change configuration. Blindly bumping memory or rewriting the compose file usually masks the real cause and produces a container that fails a week later for the same reason.

Terminal showing docker inspect output with the exit code, OOMKilled flag, and error field highlighted

Step 2 - Exit 137 with OOMKilled=true: the 1 GB VPS trap

By far the most common cause on Hermes Agent, and the one the cheap VPS for AI agent guide warns about. The agent itself is not heavy at idle, but the moment you send it a long conversation, a voice message, or an MCP tool call, memory rises fast. On a 1 GB VPS with no swap, the kernel OOM killer picks the largest process (the gateway) and ends it. Docker's restart policy immediately starts a new container, which allocates memory the same way, and gets killed the same way. That is your loop.

Confirm it in the kernel log:

sudo dmesg -T | grep -i -E 'oom-kill|killed process' | tail -5
# or on systemd hosts:
sudo journalctl -k --since '30 minutes ago' | grep -i oom

You will see a line naming the container's main process (hermes or node) and its RSS at the moment of the kill. Two fixes, in order of preference:

  1. Give the host more RAM. Below 2 GB, Hermes Agent will keep hitting this ceiling any time a conversation gets long or voice mode fires. The realistic floor for a comfortable single-user agent is 2 GB with swap enabled, or 4 GB without.
  2. Add swap on the host. On a Linux VPS: sudo fallocate -l 2G /swapfile && sudo chmod 600 /swapfile && sudo mkswap /swapfile && sudo swapon /swapfile, then persist it in /etc/fstab. Swap is slower than RAM but is the difference between a killed container and a slow response.

If you set an explicit mem_limit in your compose file, check it too. A limit under 1 GB reproduces the OOM behavior even on a large host. Remove the limit or raise it to at least 1.5 GB before restarting.

Step 3 - Exit 1 or 2 with a config error in the logs

If the exit code is 1 or 2, Hermes Agent booted far enough to run its own validation and rejected the config. The logs will show what failed. Three shapes account for most of them:

  • Missing or malformed .env. The gateway will not start without a valid provider key. Look for Provider key not set or Missing TELEGRAM_BOT_TOKEN in the logs. Check the .env file has no stray quotes around values (OPENROUTER_API_KEY="sk-..." is fine, OPENROUTER_API_KEY = "sk-..." with spaces is not) and no Windows line endings (file .env should say ASCII text, not CRLF).
  • Data directory unwritable. If you see EACCES: permission denied, open '/data/config.json', the container is running as a non-root user and the bind-mounted host directory is owned by someone else. On the host: sudo chown -R 1000:1000 ~/.hermes/data. UID 1000 is what the image uses; do not run the container as root just to sidestep this.
  • Port already bound. bind: address already in use means another process on the host is already on port 8642. Find it with sudo lsof -i :8642 and either stop the other process or map Hermes Agent to a different host port in your compose file (ports: - "9642:8642").

None of these will resolve themselves through restarts. Fix the config, then docker compose up -d again.

Step 4 - Exit 139 or "exec format error": the ARM image trap

If the container exits within milliseconds with code 139, or Docker logs show exec /usr/bin/node: exec format error, the image you pulled does not match your host CPU architecture. This usually happens on Oracle Cloud Ampere, AWS Graviton, or a Raspberry Pi, all of which are ARM64. If you pulled an image built only for linux/amd64, the kernel cannot execute the binary and Docker keeps trying.

Check the host and image architectures:

uname -m                                   # aarch64 = ARM64, x86_64 = amd64
docker inspect hermes-agent-image \
  --format='{{.Architecture}}/{{.Os}}'     # should match uname -m

If they do not match, pull with an explicit platform tag. The official Hermes Agent image is published as multi-arch, so specifying the platform is enough:

docker pull --platform linux/arm64 hermes/agent:latest

If you built a custom image, rebuild it with docker buildx build --platform linux/arm64,linux/amd64 and push both tags. Running an ARM image on an amd64 host is the same bug in the mirror direction and produces the same 139 exit.

Step 5 - Restart policy is masking the real error

restart: always is the right default for a production agent, but during debugging it turns every startup failure into a busy loop that fills the logs and hides the first, actual error. When something is wrong, switch to a policy that surfaces the failure:

services:
  hermes-agent:
    image: hermes/agent:latest
    restart: "on-failure:3"

on-failure:3 restarts up to 3 times on non-zero exits, then gives up. The container stops with the failure visible in docker ps -a, and the logs are not overwritten by fresh boots. Once the underlying issue is fixed, switch back to restart: always or unless-stopped. The Hermes Agent debugging and observability guide covers the log-rotation setup that keeps this readable in production.

A docker-compose.yml snippet with the restart policy highlighted, alongside a docker ps output showing the container in a stopped state

When the fix is not worth the weekend

Every one of the failures above is fixable, but each of them is a Sunday afternoon lost to reading kernel logs and rewriting compose files. If you got here because your bot has been down for three days and you want to get back to actually using the agent, the managed tier exists for exactly this reason. Hermify runs Hermes Agent for you on Telegram, with the memory volume, provider keys, and restart policy pre-wired, so the container failing is not your problem to diagnose. Get started with Hermify and be back online in about a minute.

For readers who prefer to keep self-hosting, the next post to read is Hermes Agent memory and skills - the second most common reason a Dockerized agent looks broken.

Sources

Run Your Own Hermes Agent

Bring your API key, connect Telegram, and get a self-improving AI agent live in 60 seconds.

Get Started