> ## Documentation Index
> Fetch the complete documentation index at: https://docs.slipway.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Troubleshooting a deploy

> Find the cause when a deploy fails, or succeeds and the URL does not work.

Start with the deployment's own page. The phase strip shows which step stopped, the
**Logs** tab carries the build output and the container's stdout, and the **Timeline** tab
lists every event including the reason a deploy failed.

This page is keyed on what you actually see.

## The deploy is green but the URL returns 403

Your framework rejected the request's `Host` header. slipway records a
`public_host_rejected` event on the deployment, with the service and the host that was
refused. The deploy stays healthy, because the container is running correctly and is
refusing the request on purpose.

Add the service's hostname to your framework's allowed-hosts setting.

```python Django theme={"system"}
# settings.py
import os
ALLOWED_HOSTS = [h for h in os.environ.get("ALLOWED_HOSTS", "").split(",") if h]
```

```ruby Rails theme={"system"}
# config/environments/production.rb
config.hosts << ENV["APP_HOST"] if ENV["APP_HOST"]
```

```javascript Vite theme={"system"}
// vite.config.js
export default {
  server: { allowedHosts: [process.env.APP_HOST] }
};
```

Then set the variable to your service's host:

```yaml slipway.yaml theme={"system"}
services:
  - name: web
    env:
      ALLOWED_HOSTS: ${service.web.host}
```

The simplest fix during development is a wildcard, but prefer the reference above in
production.

## The deploy is green but the URL returns 404

For a **static site**, `publish:` is probably pointing at the wrong directory. It is
relative to `rootDir` and must name the directory your build writes, such as `dist` or
`build`. If the build ran but the directory was empty or missing, the upload has nothing to
serve.

For a **web service**, check the container is listening on the port you declared, and on
all interfaces rather than only loopback. A server bound to `127.0.0.1` cannot be reached
from outside its own container.

## The service never becomes healthy

The container starts and readiness never passes. For a web service the deploy fails after
five minutes with `declared port N, but nothing listened on it`, and the version that was
serving before keeps serving unless the service's **Failed deploys** setting says otherwise.
A container that exits as soon as it starts fails sooner, with its exit code. Common causes:

* **The health check path does not return 2xx.** `healthCheckPath` must answer before the
  service cuts over. A path that requires authentication, or that itself waits on a
  database, will not pass.
* **The port is wrong.** The probe targets the public port, or the first declared port.
* **The app is still starting.** A slow boot needs a `startup` probe with a longer
  `failureThreshold` rather than a longer readiness period.

## `dependsOn` never came up

A service with `dependsOn` waits for its dependency to be ready. If the dependency never
becomes ready, the dependent fails with a timeout.

Check the dependency's own logs first. A database that cannot start because its disk is
full, or an allocation below the engine's memory floor, will hold up everything behind it.

`dependsOn` is rejected on `cron` and `static` services, and the graph must be acyclic. A
cycle is reported as `a → b → a`.

## The image cannot be pulled

For a private registry, add the credentials under **Settings → Registries**. slipway
attaches them automatically to every pull in the organization that needs them, and there is
nothing to reference from the spec. See [Private registries](/organization/registries).

Also check the image is `linux/amd64`, or a multi-arch manifest that includes it.

## `no_credentials` on a service using a bucket

The bucket's `default` access key was deleted, so `${service.X.access_key_id}` and
`${service.X.secret_access_key}` no longer resolve.

Create a `default` key again from the bucket's **Keys** tab, or point the references at a
named key. See [Object storage](/data/object-storage).

## `self_reference` on a database's own password

The database's password was set to a reference back to itself, usually
`${service.<name>.url}` picked from the value picker. Its connection URL is built *from*
the password, so there is no value for the reference to resolve to.

slipway now refuses the deploy instead of substituting one level and booting the engine
with the result. Rotate the password from the service's **Credentials** tab, which
generates a real one and applies it to the live database, then redeploy the services that
connect to it.

A service referencing its own `host`, `port` or `public_url` is fine and unaffected — those
describe where it is served, not how to log in.

## `unresolved_password` on a service using a database

The database this service references has no usable password: its password secret still
holds a `${…}` reference that never resolved. Embedding it would produce a connection
string that looks complete and fails authentication at runtime.

Rotate the database's password from its **Credentials** tab, then redeploy.

## A paused database's deploy waits, then fails

A managed database that is paused runs no pods, so a deploy that waits for it to
become ready waits for something that cannot happen. slipway now starts the database as
part of the deploy, the same way an ordinary service's replica count comes back from its
spec, so this resolves itself.

If a deploy still reports a paused database, start it from the service header and deploy
again. Managing credentials on a paused database also starts it, because the change has to
be made inside the running engine.

## `resources_clamped` on the deployment

The spec asked for more CPU or memory than your plan allows for one service, so slipway
deployed at the ceiling instead of failing. The deploy is healthy and running smaller than
requested.

Lower the request, or raise the plan. See [Plans](/plans).

## Two sources declare the same service name

Service names are unique within a project, because siblings reach each other by bare name.
slipway refuses to deploy a service whose name another source already publishes, and
records `service_name_conflict`.

Rename one of them. The console's create flow disambiguates automatically, so this
generally comes from two hand-written specs.

## The spec will not parse

slipway validates before anything runs and reports the line. These are the errors that come
from the format changing.

| Message | Fix |
| - | - |
| `services: must be a list of service blocks, each starting with "- name: <service>"` | The retired map form keyed by service name. Convert to a list. |
| `build fields are flattened onto the service` | Remove the `build:` block and move `rootDir`, `dockerfilePath`, `dockerTarget`, `buildArgs`, `runtime`, `runtimeVersion` and `buildCommand` up to the service. |
| `named volumes were replaced by disk:` | Replace `volumes:` with `disk: {mountPath, sizeGB}` on the service that uses it. |
| `predeploy moved onto the service as preDeploy: [command]` | Move the top-level `predeploy:` onto the service. |
| `spelled workDir now` | `workdir` is `workDir`. |
| `spelled dependsOn now` | `depends_on` is `dependsOn`. |
| `prefix moved to the service level` | `prefix` and `domain` sit on the service, not inside a port entry. |
| `` `size:` was replaced by `cpu:` and `memory:` `` | Set the allocation directly, for example `cpu: 0.5` and `memory: 1GB`. |

Other frequent validation errors:

| Message | Cause |
| - | - |
| `a managed database must be reproducible` | `version: latest` on a `databases:` entry. Pin a real version. |
| `has no version` | The version is not one slipway offers for that engine. The message lists the offered versions. |
| `a database without a disk loses its data on restart` | A non-Redis `databases:` entry with no `diskSizeGB`. |
| `worker services cannot declare ports` | Only `type: web` may declare ports. |
| `prefix/domain need a public hostname` | Mark a port `public: true`, or drop the `prefix` and `domain`. |
| `static sites are free — cpu/memory do not apply` | Remove `cpu:` and `memory:` from a `type: static` service. |
| `type: static requires publish` | Name the directory your build writes. |
| `runtimeVersion requires a language runtime` | Set `runtime:` alongside it. |
| `a language runtime and dockerfilePath/dockerTarget are mutually exclusive` | A runtime generates its own Dockerfile. Choose one source. |

## A build fails

The build output is in the deployment's **Logs** tab, under the service being built.

* **A dependency is missing.** The build runs in a clean container, so anything not in your
  lockfile or install step will not be there.
* **The lockfile is out of sync.** `npm ci` refuses a `package-lock.json` that disagrees with
  `package.json`, which npm on macOS produces by leaving out optional packages for other
  platforms. The build falls back to `npm install` and says so in the log. Commit a
  regenerated lockfile to get exact installs back. pnpm and yarn get the same fallback.
* **The build ran out of memory.** Raise the [build machine](/deploys/build-machine).
* **A base image moved.** Choose **Rebuild without cache** from the Deploy latest dropdown.
  See [How deploys work](/deploys/how-deploys-work#rebuilding-without-the-cache).

## A push did not deploy anything

Check three things, in order:

1. **Auto-deploy is on** for that service. It defaults on for a single-repo project and
   off for sources added to a multi-repo project.
2. **The push was to the tracked branch.** A source deploys one branch.
3. **A `buildFilter` did not skip it.** If no changed file matched, the deploy is skipped
   by design. See [Monorepos](/deploys/monorepo).

A manual deploy always runs, which is the quickest way to tell a filter from a
misconfiguration.

## The balance ran out

Projects pause when an organization's balance reaches zero. Nothing is deleted and disks
keep their contents. Add balance and resume them. See [Billing](/organization/billing).

## Still stuck

Open **Help** in the console to reach the slipway team with the deployment already
attached, or use the [MCP server](/integrations/mcp) to let an agent read the logs and
events directly.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.