Troubleshooting
“container_name not authorized for this session”
Section titled ““container_name not authorized for this session””This error appears in the errors[] array of the sync response when you pass a container_name to POST /external-deploy/sync that was not included in the session’s authorized list.
Root cause: The session was created with a specific set of container names (from POST /external-deploy/session). The sync call included a container name that was not in that set — either because it was not passed to the session endpoint or because it did not match any Application at session creation time.
What to check:
- Open the Application in the Reoclo dashboard and verify the Linked Container Name field matches the container name exactly (case-sensitive, no extra whitespace).
- Ensure the container name in your Compose file’s service definition — or in your
servicesaction input — matches the Application’slinked_container_name. - If using a Compose file, confirm the service is on the
reoclo-proxynetwork or labeledreoclo.managed=true, otherwise it is not submitted at session creation and cannot be synced.
”Deploy session expired”
Section titled “”Deploy session expired””The rds_ session token expires approximately 15 minutes after creation. If your workflow takes longer than that between the session creation step and the sync step, the sync call returns a 401 with this message.
The action does not automatically renew sessions. To recover:
- Rerun the failed job in GitHub Actions. The action creates a fresh session at the start of each run.
- If your workflow consistently takes more than 15 minutes before reaching the sync step, move the sync step earlier — immediately after the
docker compose up/docker runstep rather than after unrelated steps.
409 Conflict on /sync
Section titled “409 Conflict on /sync”A conflict status in the results (or a top-level 409 if all deployments conflict) means Reoclo received a sync request with a different configuration from the one it recorded less than 30 seconds ago. This is a race-guard to prevent two concurrent workflow runs from overwriting each other’s proxy routes.
Common causes:
- Two workflow runs triggered in quick succession (e.g. two fast pushes to
main). - A re-run of a failed job while a parallel run is still in progress.
To force the update when you are certain the new configuration is correct, set the force: true input on the reoclo/deploy-sync@v2 step. If you drive the API directly instead of the action, pass force: true on the relevant deployment entry in the POST /external-deploy/sync body (shown below).
curl -X POST https://api.reoclo.com/external-deploy/sync \ -H "Authorization: Bearer rds_example_DO_NOT_USE_xxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "deployments": [ { "container_name": "myapp-web", "container_port": 3000, "image_tag": "ghcr.io/myorg/myapp:abc123", "force": true } ] }'If you simply wait 30 seconds and rerun, the conflict window will have passed and the sync will proceed normally.
Sites still return 502 after sync
Section titled “Sites still return 502 after sync”A synced result means Reoclo updated the proxy route record and triggered the Caddy reconciler. If your site still returns 502, the problem is almost always that Caddy cannot reach the container.
Caddy resolves container_name by DNS inside the reoclo-proxy Docker network. For this to work:
- The container must be running on the server.
- The container must be attached to the
reoclo-proxynetwork. - The port in the proxy route must match the port the container is actually listening on.
Diagnosis steps:
-
SSH into the server and run:
Terminal window docker network inspect reoclo-proxy --format '{{range .Containers}}{{.Name}} {{end}}'Your container name must appear in the output. If it does not, add
reoclo-proxyto the service’snetworksin your Compose file and redeploy. -
Verify the container is listening on the expected port:
Terminal window docker inspect myapp-web --format '{{json .NetworkSettings.Ports}}' -
Check Caddy’s error log in the Reoclo dashboard under the server’s Proxy tab for the specific upstream error.
See Compose Deployments for the correct network configuration.
403 on POST /external-deploy/session
Section titled “403 on POST /external-deploy/session”The rca_ key used to create the session does not have external_deploy in its allowed operations.
Go to API Keys > Automation Keys in the dashboard, find the key, and add external_deploy to Allowed Operations. The change takes effect immediately — no need to rotate the key.
400 “None of the supplied identifiers matched an application” on session creation
Section titled “400 “None of the supplied identifiers matched an application” on session creation”None of the identifiers you submitted to POST /external-deploy/session matched an Application in your tenant. The error lists exactly what you submitted and your known Applications (slug → container) so you can see the mismatch at a glance.
Most common cause — the name Reoclo received isn’t the name your Application is linked to. When discovering from a Compose file, Reoclo uses the service’s container_name: if set, otherwise the service key (e.g. app). The running container is usually named <project>-<service>-<index> (e.g. myapp-app-1), which is what the dashboard records when you link by scanning the server — so app ≠ myapp-app-1 and nothing matches.
Fixes (pick one):
- Bind by label (recommended). Add
reoclo.app: <your-app-slug>(orreoclo.app-id: <uuid>) to the service. Identity no longer depends on the container name at all. See Matching a service to its Application. - Make the names agree. Set an explicit
container_name:on the service and link the Application to that exact name. - Add an alias or pattern to the Application. Set
linked_container_names(e.g.["app"]) orlinked_container_name_pattern(e.g.myapp-app-*) so the Application answers to the name Reoclo receives.
Also confirm the Applications belong to the same tenant as the rca_ key.
App can’t reach its database after deploy (EAI_AGAIN postgres)
Section titled “App can’t reach its database after deploy (EAI_AGAIN postgres)”If a routed app crash-loops on startup unable to resolve postgres/redis (getaddrinfo EAI_AGAIN), but the database container itself is healthy, the app lost its private network and is left on reoclo-proxy only.
This was a managed-proxy reconciliation bug on API < 1.74.1: recreating the app to strip a host-port publish collapsed it onto a single network. As of 1.74.1 reconciliation is additive — it preserves every network and alias the container had. Upgrade the server’s API and redeploy; the next recreate restores the private network. See Keeping a private database network.
Drift notifications
Section titled “Drift notifications”Reoclo sends a tenant notification when it detects that a live container has drifted from its last recorded deployment state. These notifications are emitted by the proactive drift scan, which runs roughly every 30 minutes against every active deployment signature.
When notifications fire
Section titled “When notifications fire”Notifications fire on state transitions only, not on every scan tick. If a
container has been missing for 24 hours, you receive one notification — not 48.
A second notification fires when the container comes back in sync
(DRIFT_RESOLVED).
The UNREACHABLE status (runner could not be contacted) is never emitted as a
notification. Persistent runner unreachability is surfaced by the server health
checks instead.
Drift status values
Section titled “Drift status values”| Status | What it means | How to fix |
|---|---|---|
image_mismatch | The container is running but with a different image tag than the last recorded deployment. | Re-run the deploy workflow to push the correct image, or call POST /external-deploy/sync with force: true if the running image is intentional. |
container_missing | The expected container is absent or stopped on the server. | Check whether the container crashed (docker logs <name>) or was removed manually. Redeploy via your workflow. |
not_attached | The container is running but not connected to the reoclo-proxy network. Traffic routing will fail. | Add reoclo-proxy to the container’s networks and restart it, or redeploy with the correct Compose network config. |
ok (resolved) | The container is back in sync with the recorded deployment. | No action needed — this is the resolution notification. |
What drift notifications look like
Section titled “What drift notifications look like”Notifications appear in the Reoclo dashboard under the bell icon and in any configured notification channels (email, Slack, etc.). The title is “External deploy drift detected” for new drift, and “External deploy drift resolved” when the container comes back into sync.
The notification body contains the container name and a plain-language
description of the specific drift type. The server_id and application_id
fields are attached so integrations can correlate the notification with the
affected resource.
status: drift_recovered in results
Section titled “status: drift_recovered in results”This is a healthy signal, not an error.
drift_recovered means Reoclo received your sync call, had no prior signature
record for this container configuration, and then inspected the live server and
found that the container was already running the correct image and already
attached to the reoclo-proxy network. Reoclo recorded the deployment fact
(proxy routes and a new signature) without making any changes to the container
or Caddy configuration.
Your site is fine. The route is correct. No action is required.
Common causes:
- The workflow that deployed the container did not include the Reoclo sync step, so Reoclo is learning about the deploy after the fact.
- A server reboot or infrastructure recovery left containers intact but cleared Reoclo’s signature records.
- This is the first sync call after the External Deployment feature was enabled on a server that was already running containers.
What to check (only if curious, not because anything is broken):
- Open the workflow that deployed this container and confirm it calls the
Reoclo sync action. If it does not, add the sync step after your
docker compose up/docker runcall — future deploys will then producestatus: syncedinstead. - If
drift_recoveredappears repeatedly for the same application on every deploy, the sync step is likely missing from the deploy workflow entirely.