# Troubleshooting and error codes

Fixes for common problems, and every Deplane error code with what it means and how to fix it.

Every error from the CLI and the API has a stable `code`, a `message` that says what happened, and a `fix` that says what to do. API errors also carry a `docs` link to the matching section of this page and a `request_id` to quote when you email support@deplane.io.

## Common problems

### Cannot log in

- Run `deplane doctor`. It checks that the API answers and that your login works.
- If `DEPLANE_TOKEN` is set, the CLI uses it instead of your login. Unset it to use `deplane login`.
- The login code expires after 10 minutes. Run `deplane login` again for a new one.
- Type the code shown in your terminal on https://app.deplane.io/device. Approve only a request you just started yourself.
- Sign-in links work once and expire after 15 minutes. Request a new one on the sign-in page.
- After too many wrong authenticator codes, codes are locked for a while. Use your passkey instead.
- Deplane is invite-only during the beta. Your email must have an approved access request.

### Build failed

The CLI exits with code 3 and shows the build log. Look at the last lines of the log for the step that failed.

- Without a Dockerfile, Deplane works out the build from your project files. If it cannot, add a Dockerfile, or check the messages in the log. See [railpack_plan_failed](#railpack_plan_failed).
- A build has 15 minutes, 3 GB of memory, and 10 GB of disk. See [build_timeout](#build_timeout), [build_out_of_memory](#build_out_of_memory), and [build_disk_full](#build_disk_full).
- Private packages need a token while building. Set it as a build secret: `deplane secrets set --build NPM_TOKEN=...`. See [Secrets](secrets.md).
- If the upload is too large, add `node_modules`, build output, and data files to `.dockerignore` or `.gitignore`.

### Deploy failed

The build worked but the new release did not become healthy. The CLI exits with code 4, the release is marked failed, and the previous release keeps serving. `deplane status` shows the reason and the fix:

| Reason | What it means | Fix |
|---|---|---|
| `Unschedulable` | There is not enough room for this size right now. | Use a smaller size or fewer instances (`deplane scale 1 --size small`), or try again later. |
| `ImagePullFailed` | Deplane could not fetch the release's image. This is a problem on our side and we have been alerted. | Run `deplane deploy` again in a few minutes. |
| `HealthCheckFailed` | The app started but did not answer its health check on its port. | Make the app listen on `0.0.0.0` at the port in `$PORT`, and make `health_check` (if set) answer 200. Run `deplane logs` to see why it failed. |
| `Crashing` | The app stops soon after it starts. If it ran out of memory, the message says so. | Run `deplane logs` to see the error, fix it, and run `deplane deploy`. For memory, use a larger size: `deplane scale --size medium`. |
| `Timeout` | The new release did not become healthy within 5 minutes. | Run `deplane logs`, fix the problem, and run `deplane deploy`. |
| `ReleaseCommandFailed` | The app's [release command](release-command.md) failed, so the new release never started. The last lines of its output are shown. | Fix the command or the code it runs, and run `deplane deploy`. It runs again with the next deploy, so make it safe to run twice. |

### App not reachable

- Run `deplane status`. `State` should be `Running` with all instances ready.
- If you scaled to 0, nothing is running. Run `deplane scale 1`.
- Your app must listen on `0.0.0.0`, not `127.0.0.1` or `localhost`, at the port in `$PORT`.
- A request that gets no first byte back within 125 seconds times out. See [Limits](limits.md).
- If the app is suspended, `deplane status` shows `suspended`. Email support@deplane.io.
- If visitors see "This site has reached its monthly bandwidth limit", see [limit_bandwidth](#limit_bandwidth).

### Quota reached

Errors whose code starts with `limit_` mean you reached a plan limit, and the CLI exits with code 6. Run `deplane whoami --json` to see your limits and `deplane apps` to see what uses them. Destroy or scale down apps you no longer need, or email support@deplane.io to raise the limit. See [Limits](limits.md).

## Error codes

Exit codes: codes starting with `limit_` exit with 6. Build failures exit with 3 and deploy failures with 4. Other API errors exit with 2 for authentication and permission problems, 5 for problems on our side, and 1 for everything else, including a suspended app (`app_suspended`). Some codes appear only in the web pages for signing in, not in the CLI.

### access_denied

The login or confirmation request was denied in the browser.

Fix: run the command again if that was a mistake.

### access_request_reviewed

An admin tried to approve or deny a beta access request that was already approved or denied.

Fix: list open requests with `deplane admin requests`.

### account_suspended

Your account or organization is suspended. Its tokens no longer work and its apps run zero instances.

Fix: email support@deplane.io. See [Reporting abuse](abuse.md) for what suspension means and how to appeal.

### admin_cannot_join

A platform admin account cannot join a customer's team.

Fix: view the team read-only from the admin console, or ask for an invitation to another address.

### alerts_unavailable

Alerts are not available on this server.

Fix: Try again later.

### already_current

You asked to roll back to the release that is already current.

Fix: pick an earlier version from `deplane releases`.

### already_member

The address you invited is already in your team.

Fix: nothing to do.

### already_suspended

An admin tried to suspend an app or organization that is already suspended.

Fix: nothing to do. To change the reason, unsuspend it with `deplane admin unsuspend` and suspend it again.

### app_has_database

The app already uses another database as its DATABASE_URL.

Fix: detach that database first, then attach this one.

### app_name_brand

App names cannot contain a well-known brand name, such as `paypal` or `google`. Common letter swaps such as `paypa1` count too. This protects people from phishing.

Fix: pick a name without the brand. If you own the brand, email support@deplane.io.

### app_name_reserved

The name is reserved by Deplane, for example `api`, `www`, or `admin`.

Fix: pick another name, for example `api-app`.

### app_exists

`deplane launch --name NAME` named an app your organization already has, from a folder that is not that app's. Launch never deploys one folder over another app.

Fix: to deploy this folder to that app on purpose, run `deplane deploy --app NAME`. To create a new app, pick another name with `--name`.

`deplane import heroku` refuses the same way when your team already has an app with the name it would create, before it creates anything. Pick another name with `--name`, or, if an earlier import created that app, delete it with `deplane apps destroy NAME` first.

### app_name_taken

Another app already has this name. Names are unique across Deplane, and the name of a deleted app stays reserved for its team for 90 days, so nothing still pointing at the old address reaches another team's app.

Fix: pick another name with `deplane launch --name NAME`. Without `--name`, `launch` picks a free name for you.

### app_not_found

There is no app with this name in your organization.

Fix: check the `app` in `deplane.toml` or the `--app` flag, or run `deplane launch` to create the app. `deplane apps` lists your apps.

### app_suspended

This app is suspended, so it cannot be deployed or changed. The CLI exits with code 1.

Fix: email support@deplane.io to resolve the suspension.

A restore of another ClickHouse database's backup gives the attached apps a new `CLICKHOUSE_URL`, so it is refused while one of them is suspended. Fix: detach that app first with `deplane clickhouse detach NAME --app APP`, then restore again.

### app_unavailable

The app was destroyed or suspended while it was building, so no release was created.

Fix: if the app still exists, run `deplane deploy` again.

### apply_error

The live import stopped because the new database could not apply a change from your database for 10 minutes: the change failed, and the copying paused so nothing would be applied out of order. This happens when something wrote to the new database while the import was syncing (for example a row with a key that then also arrived from the source), or when the source's schema changed. Nothing more was copied after the failed change.

Fix: do not write to the new database until the import is done. Delete the new database, then start a new import. If the source's schema changed, start the new import after the change.

### apps_unavailable

New apps cannot be created in this team yet.

Fix: try again later.

### assistant_failed

The assistant could not answer right now, usually because the AI service did not respond in time.

Fix: Ask again in a moment.

### assistant_monthly_limit

Your team asked the assistant as many questions this month as your plan includes.

Fix: It resets on the 1st (UTC). To raise it, email support@deplane.io.

### assistant_not_in_plan

The assistant is not included in your team's plan.

Fix: Email support@deplane.io to turn it on.

### assistant_rate_limited

You asked the assistant 40 questions in the last hour, the most allowed.

Fix: Wait a few minutes and ask again.

### assistant_unavailable

The assistant is not set up on this Deplane installation yet.

Fix: Use the dashboard, `deplane status` and `deplane logs` meanwhile.

### authorization_pending

The login or confirmation request is waiting for approval in the browser. The CLI keeps waiting; you only see this code if you call the API yourself.

Fix: approve the request in your browser.

### backup_changed

The full copy or stream a restore was about to start from was deleted by retention at the same moment, so the restore was not started.

Fix: run the restore again; it starts from the backups that are there now.

### backup_not_restorable

That disk backup cannot be restored: it did not finish (`failed`, or still under way). Any backup marked `done` in the list can be restored.

Fix: pick a backup marked `done` from `deplane disks backups APP`. For a MySQL, any finished backup of your team's MySQL can be restored, including a destroyed one's: `deplane mysql backups NAME` or `deplane mysql backups --destroyed` lists them. For a ClickHouse database, likewise: `deplane clickhouse backups NAME` or `deplane clickhouse backups --destroyed`. Another team's backup gets this answer too. See [MySQL](mysql.md#backups-and-restore) and [ClickHouse](clickhouse.md#backups-and-restore).

### backup_running

A backup of this disk is already under way.

Fix: wait for it to finish; `deplane disks backups APP` shows it. A restore cannot start during a backup either.

### backup_too_soon

This disk was already backed up on request in the last hour. You can ask for a backup at most once an hour; the disk is also backed up every night. After a backup on request fails, you can try again 5 minutes later.

From `deplane import cpanel` on a live site (`--replace-live`, or the domain typed), this means the import needs a disk or MySQL backup taken for this run and one ran within the hour, so nothing was deleted: an older backup would miss what changed since.

Fix: try again after the time in the message.

### backups_off

Deplane's database backups are switched off right now (for example during maintenance), so a restore cannot start.

Fix: try again later, or email support@deplane.io if you need a copy of your data now.

### bad_credentials_file

The file where the CLI stores your login, `credentials.json` in your config folder, is not valid JSON.

Fix: delete the file the message names and run `deplane login` again.

### bad_response

The API sent a response the CLI cannot read, or a login was approved without a token.

Fix: update the CLI, then try again. For a login, run `deplane login` again.

### bad_teams_file

The file where the CLI remembers which of your teams have a login on this computer (`teams.json` in its config folder) is not valid JSON.

Fix: delete it and run `deplane login` again.

### body_too_large

The request body is larger than the API accepts: 64 KB, except source uploads.

Fix: send less than 64 KB. For uploads, use `deplane deploy`.

### build_capacity

Deplane had no free build capacity for 5 minutes, so the build did not start. Builds normally start within seconds: one build's worth of capacity is kept free.

Fix: deploy again in a few minutes. If it keeps happening, email support@deplane.io.

### build_disk_full

The build used more than 10 GB of disk, the limit.

Fix: keep large files out of the build with `.dockerignore`, and clean package caches in the same step that fills them.

### build_expired

The build waited in the queue for more than an hour and was not started.

Fix: run `deplane deploy` again.

### build_failed

A step of the build failed.

Fix: see the build log for the step that failed, fix it, and run `deplane deploy` again.

### build_interrupted

The build was interrupted on our side and did not finish.

Fix: run `deplane deploy` again.

### build_out_of_memory

The build ran out of memory. A build has 3 GB.

Fix: lower the build's memory use, for example with fewer parallel jobs, or for Node with `NODE_OPTIONS=--max-old-space-size=2048` set as a build secret.

### build_platform_error

The build could not run because of a problem on our side.

Fix: run `deplane deploy` again. If it keeps happening, email support@deplane.io.

### build_start_failed

The build could not be started.

Fix: run `deplane deploy` again. If it keeps happening, email support@deplane.io.

### build_timeout

The build took longer than 15 minutes, the limit. The CLI also uses this code if it stops waiting for a build.

Fix: make the build faster, for example by removing unused dependencies or build steps, then run `deplane deploy` again. Run `deplane status` to see where a build is.

### builds_unavailable

Builds are not available right now.

Fix: try again in a few minutes. If it keeps happening, email support@deplane.io.

### capacity_full

Deplane's servers are nearly full: a new app, a preview, a scale-up, a new or bigger worker or cron job, a new or restored database, a new Redis, a new MySQL, a new ClickHouse database, or a template deploy would take the servers' reserved memory or CPU above 85% of what they hold. Apps that already run are not affected, and we are alerted to add capacity. The CLI exits with code 5.

Fix: try again later, or use a smaller size or fewer instances.

### cancelled

You answered no to a confirmation, or stopped the command.

Fix: run the command again. Pass `--yes` to skip the question.

### cannot_remove_self

You tried to remove yourself from the team.

Fix: ask another owner to remove you.

### cannot_suspend_own_org

An admin tried to suspend their own organization. That would lock them out of `deplane admin unsuspend`.

Fix: ask another admin to do it.

### check_failed

The import check connected to your database but could not read what it needs to know about it, for example because a query was refused or the connection dropped. The message says what the database answered.

Fix: make sure the user in the URL can read the database's tables and system catalogs, then run the check again. If it keeps happening, email support@deplane.io.

### ci_token_not_allowed

CI tokens cannot create, list, or revoke tokens, invite or remove team members, confirm actions, destroy apps, delete, restore or switch databases, forget stacks, or run admin commands.

Fix: do it in the dashboard, or from your own machine after `deplane login` (the CLI asks you to confirm in your browser). A CI token can revoke itself with `POST /v1/logout`.

CI tokens also cannot import databases: an import's URL carries the source database's password.

Fix: import from the dashboard, or from your own machine after `deplane login`.

### cleanup_failed

A cancelled or failed live import removed what it made on your database, but Deplane could not remove the import's subscription from the new database, which still tries to copy from a source that no longer serves it.

Fix: email support@deplane.io with the import's ID, or delete the new database if you no longer need it.

### counts_differ

Finish compared the row count of every table on your database with the new database's, and they differed, so it changed nothing: the import keeps syncing. The message names up to five tables with both counts. Usually your app was still writing to the source.

Fix: stop every write to the source database, wait a moment, then finish again.

### disk_exists

The app already has a disk. An app has at most one.

Fix: use the disk it has (`deplane disks list`), or destroy it first with `deplane disks destroy APP`.

### disk_needs_one_instance

An app with a disk runs one instance. It cannot be given a disk while it runs more than one instance or autoscales, and with a disk it cannot be scaled above one instance or set to autoscale. See [Disks](disks.md).

Fix: scale to 1 instance and turn off autoscaling first: `deplane scale 1 --max 0 --app APP`.

### disk_not_found

The app has no disk.

Fix: add one with `deplane disks create APP`. `deplane disks list` shows your team's disks.

### disk_on_preview

Pull request previews cannot have a disk. They run without the disk of their app.

Fix: add the disk to the app itself.

### follow_with_range

`deplane logs --follow` reads live lines, so it cannot be combined with `--since`, `--until` or `--search`.

Fix: drop `--follow` to read kept logs, or drop the others to follow live lines.

### finish_failed

Finish could not complete, for example because the new database or the source dropped the connection, or the import's replication slot on the source is gone. The message says what failed. The import keeps syncing when it can.

Fix: finish again. If it keeps happening, cancel the import and start a new one, or email support@deplane.io with the import's ID.

### invalid_disk_path

The disk's path is not allowed. It must be absolute, use lowercase letters, digits and `. _ / -`, have no `..` part, and not be `/` or a system folder: `/proc`, `/sys`, `/dev`, `/etc`, `/bin`, `/sbin`, `/lib`, `/usr`, `/var/run`, `/run`, or anything under them.

Fix: use a path such as `/data` (the default) or `/srv/files`.

### invalid_team

`deplane login --team` was given something that is not a team slug.

Fix: run `deplane teams` to see your teams' slugs.

### invite_sign_in

The address this invitation is for already has an account. The link alone never signs anyone in to an existing account.

Fix: sign in with that account, then open the invitation link again and press Join.

### invite_wrong_account

You are signed in with a different address than the one the invitation is for.

Fix: sign out, sign in with the address the invitation was sent to, then open the link again.

### limit_disk

Your team's disks together would use more disk space than your plan allows. Every disk is 5 GB; Free allows 5 GB (one disk), Hobby 10 GB, Pro 50 GB.

Fix: destroy a disk you no longer need with `deplane disks destroy APP`, or email support@deplane.io to raise the limit.

### live_failed

The live import could not set up the copying of changes: on your database, the publication or the replication slot could not be made, or in the new database the subscription could not be. It also stops here when something live mode needs is no longer true, for example a new table without a primary key, or when a table was created or dropped on the source just as the import started. The message says what failed.

Fix: fix what the message names on the source (a check shows what live mode needs), then start a new import, or choose copy mode.

### mcp_database_url

AI tools connected to Deplane, such as Claude, cannot set `DATABASE_URL`, at run time or at build time. Nothing was changed.

Fix: have the tool attach a database (`attach_database`). To set `DATABASE_URL` by hand, or to switch apps to a restored database, do it yourself in the dashboard or with the CLI.

### mcp_not_allowed

AI tools connected to Deplane, such as Claude, can call only what their tools need. Everything else is refused: deleting or detaching things, app settings (an AI tool sets only the port of an image it deploys), alert settings and channels, the activity log, tokens, the team, the assistant, connections and admin features.

Fix: do it yourself in the dashboard.

AI tools cannot check, start, finish or cancel a database import either: an import's URL carries a database password that must not enter an AI context. They can follow an import's progress, which never shows the URL.

Fix: import it yourself in the dashboard, or with `deplane db import`.

AI tools cannot import from Heroku, or read or cancel the imports from Heroku either: the Heroku token reads every config var of the app, and neither it nor the values may enter an AI context. In the database imports they can follow, one that copies a Heroku app's database shows no host, port, database, table or schema names, only a fixed sentence.

Fix: import it yourself, with **Import from Heroku** in the dashboard or `deplane import heroku` on your machine.

AI tools cannot run commands (`deplane run`) or read a run's output either: a run has the app's secrets and does whatever its command says. Asking the logs for a run's output is refused; a run's lines are left out of the logs an AI tool reads.

Fix: run it yourself with `deplane run`.

### mcp_needs_connection

The MCP endpoint accepts an AI tool's OAuth connection or a CI token. It refuses the login token that `deplane login` stores on your machine.

Fix: add Deplane to your AI tool with the server URL; it opens a browser to connect. Or use a CI token.

### confirmation_required

The command needs a yes or no answer, and no terminal is attached, so the CLI did not ask.

Fix: pass `--yes` to confirm.

### copy_failed

The import could not copy your database. The message says what failed, for example an object the new database could not create, or a connection to the source that dropped. Nothing of the copy was kept in the new database. In the rare case that Deplane could not empty it afterwards, the message says so: delete that database before you import again.

Fix: fix what the message names on the source, or leave its schema out, then start a new import. If it keeps happening, email support@deplane.io with the import's ID.

### csrf_failed

A form on the sign-in site expired or did not come from that site.

Fix: go back, reload the page, and try again.

### database_capacity

The platform has no free pair of database disks (a database uses one disk for each of its two copies), so Deplane did not create the database (or the restore's new database). Nothing was created and nothing is charged. A MySQL or a [ClickHouse database](clickhouse.md) uses one database disk, and leaves a few free for databases, so it can get this answer while a database still fits.

Fix: try again later. If it keeps happening, email support@deplane.io.

### database_exists

Your team already has a database with that name.

Fix: pick another name.

### database_failed

An AI tool asked to attach a database that could not be created.

Fix: open the database in the dashboard's Databases page to see why, then create it again.

### database_being_copied

The database is being copied into a new database (`deplane db copy`, or **Copy to a new database** in the dashboard), so it cannot be deleted until the copy ends.

Fix: wait for the copy to end (`deplane db import status` shows it), or cancel it with `deplane db import cancel`, then delete it.

### database_busy

Another delete of this database is still running, and this one waited 30 seconds for it.

Fix: try again in a minute. If the database is gone by then, the first delete finished.

### database_importing

An import into this database is still in progress, so it cannot be attached to an app, deleted, restored, used as the source of a restore, or switched to or from.

Fix: finish the import (live mode) or wait for it to end (copy mode), or cancel it, then try again. `deplane db import status` shows where it is.

### database_not_ready

An AI tool asked to attach a database that is still being created. A new database is ready in about a minute.

Fix: the tool calls attach_database again in a minute.

### deploy_failed

The new release did not become healthy. It was marked failed, and the previous release keeps serving. The message gives the reason: `Unschedulable`, `ImagePullFailed`, `HealthCheckFailed`, `Crashing`, `Timeout`, or `ReleaseCommandFailed`.

Fix: follow the fix in the message. The table in [Deploy failed](#deploy-failed) lists each reason. `deplane logs` shows the app's output.

### deploy_in_progress

An AI tool asked to deploy an app that already has a build queued or running. AI tools deploy one version of an app at a time.

Fix: the tool calls wait_for_deploy with the build ID in the message, then deploys again.

### deploy_replaced

A newer deploy of the app took over while this release was still rolling out, so this release never went live. It is listed as `replaced` in `deplane releases` and is never a rollback target. The exit code is 4.

Fix: nothing to fix here. The newer deploy is the one going live: run `deplane status` to follow it.

### deploy_timeout

The CLI stopped waiting because the release did not finish rolling out in time.

Fix: run `deplane status` to see what is happening, and `deplane logs` for the app's output.

### detect_failed

Deplane could not tell how to build this folder.

Fix: run the command in your project's root folder. Deplane builds Node, Python, Go, Ruby, PHP, Java, and static sites without configuration, and any project with a Dockerfile. See the [Quickstart](quickstart.md#what-launch-detects).

### device_code_invalid

The login code you typed is not valid or has expired.

Fix: check the code shown in your terminal, or run the command again for a new one.

### device_wrong_account

The login or confirmation request was started by a different Deplane account than the one signed in to the browser.

Fix: sign in with the account that ran the command.

### dockerfile_syntax_not_allowed

The Dockerfile starts with a `# syntax=` line, which would load a build tool from outside Deplane.

Fix: remove the `# syntax=` line. Deplane builds with the standard Dockerfile support, which handles current Dockerfile features.

### dockerfile_too_large

The Dockerfile is larger than 1 MB.

Fix: shorten the Dockerfile.

### domain_dangling

Another team had this domain connected to its app on Deplane, removed it or deleted the app, and the domain's CNAME still points at that old app's address. Deplane does not let a leftover DNS record hand the domain to someone else.

Fix: whoever controls the domain's DNS must change the CNAME to your app's address (shown in the Domains tab), then add the domain again. If you do not control the domain's DNS, you cannot connect it.

### domain_taken

The custom domain is already connected to an app on Deplane, possibly in another organization.

Fix: if the domain is yours, remove it from the other app first. If you do not recognize the other app, email support@deplane.io.

### email_unavailable

Sign-in links by email cannot be sent on this site right now (its email sender is not set up). The answer is the same for every address.

Fix: sign in with your passkey, or contact support.

### expired_token

The login or confirmation code expired before it was approved, or was already used.

Fix: run the command again.

### github_already_linked

That GitHub account is linked to another Deplane account.

Fix: sign in to that account instead, or use a different GitHub account.

### github_app_exists

Deplane's GitHub App was already created.

Fix: Manage it on GitHub from the admin page /admin/github.

### github_authorization_failed

GitHub did not confirm that you approved Deplane seeing your repositories, or the approval expired.

Fix: Press **Connect GitHub** again and approve on GitHub.

### github_authorization_needed

Deplane does not know which of your GitHub repositories you can use yet. Approvals last an hour.

Fix: Press **Connect GitHub** in the dashboard and approve on GitHub. See [GitHub](github.md).

### github_branch_missing

The branch the app deploys from is not in the repository.

Fix: Push the branch, or pick another one in the app's **Settings**.

### github_deploy_failed

Deplane could not deploy the connected branch, for example because the repository is empty or the branch is gone. The message says which.

Fix: Fix the problem on GitHub or in the app's Settings, then run `deplane github deploy` again.

### github_deploy_slow

GitHub's commit did not reach Deplane within 2 minutes.

Fix: Run `deplane status` in a minute; the deploy may still start.

### github_link_exists

Your account is already linked to a GitHub account.

Fix: email support@deplane.io to change the linked GitHub account.

### github_login_failed

GitHub sign-in did not complete.

Fix: start again from the sign-in page.

### github_not_connected

The app is not connected to a GitHub repository.

Fix: Connect one in the app's **Settings**.

### github_not_linked

No Deplane account is linked to this GitHub account.

Fix: sign in with your sign-in link, then link GitHub from your account page.

### github_preview_app

Pull request previews follow the app they belong to and cannot be connected to a repository themselves.

Fix: Connect the app the preview belongs to.

### github_repo_empty

The connected repository has no commits yet, so there is nothing to deploy.

Fix: Push a first commit to the branch. Deplane deploys it automatically.

### github_repo_not_allowed

You have not given Deplane access to that repository, or your approval is older than an hour.

Fix: Press **Connect GitHub**. On GitHub, add the repository to the Deplane app's repository access, then pick it again.

### github_repo_not_visible

An AI tool asked to deploy a GitHub repository that the Deplane GitHub App cannot read for you.

Fix: give the Deplane GitHub App access to the repository from the app's Settings tab in the dashboard, then ask again.

### github_root_missing

The root folder set for the app is not in the repository at the commit being deployed.

Fix: Fix the root folder in the app's **Settings**, or leave it empty for the repository's root.

### github_setup_failed

GitHub did not confirm the new GitHub App. Its confirmation code works once, for an hour.

Fix: Start again from /admin/github.

### github_unavailable

Deploying from GitHub is not set up on this Deplane installation yet. A dashboard import from another platform that deploys a repository needs it.

Fix: Deploy with `deplane deploy` or by uploading a folder in the dashboard. For an import, use `deplane import` from your machine, which deploys a folder, or import the image the platform runs where it offers one. For an import, use `deplane import` from your machine, which deploys a folder, or import the image the platform runs where it offers one.

### has_account

No longer returned. An address with an account of its own is invited like any other; its owner signs in and joins (see [Team](team.md#people-in-more-than-one-team)).

Fix: nothing to do.

### http_status

The CLI got an HTTP error with no Deplane error in it, for example from a proxy. The code is `http_` followed by the status, such as `http_502` or `http_503`.

Fix: try again later. If you set `DEPLANE_API_URL`, check that it points to the Deplane API.

### image_with_source

`--image` was given together with a folder, a path or `--template`. An image deploy has no source: it deploys the image as it is.

Fix: use `--image` on its own, for example `deplane deploy --image nginxinc/nginx-unprivileged:1.27 --app web`, or leave it out to deploy a folder.

### image_invalid

The image the build produced could not be read.

Fix: run `deplane deploy` again. If it keeps happening, email support@deplane.io.

### image_not_found

The build finished, but its image could not be found.

Fix: run `deplane deploy` again. If it keeps happening, email support@deplane.io.

### import_active

Your team already has an import in progress. A team runs one import at a time, from the check until it is done, cancelled or failed.

Fix: finish or cancel that import, then start the new one.

### import_cancelled

The import was cancelled, by you or a teammate, while `deplane db import` was following it, or it was already cancelled when you looked.

Fix: run `deplane db import` to start another. The database made for the import stays, with whatever was copied; delete it with `deplane db destroy NAME`. If the message shows two SQL lines, run them on the source database: Deplane could not reach it to remove its replication slot and publication.

From `deplane redis import`, the new Redis stays, emptied; delete it with `deplane redis destroy NAME`.

### import_check_failed

The check of the source database did not finish. The message says why, for example that it could not connect, that the password was refused, or that the server does not allow TLS.

Fix: fix the URL, or let Deplane reach the source (the dashboard's import page lists the addresses a firewall must allow), then run `deplane db import` again. A team can start 20 checks a day.


From `deplane redis import`, the check of the source Redis or the file link did not finish, for example because Deplane could not connect, the password was refused, or the link answered an error. Fix the URL or link, or let Deplane reach the source (`deplane redis import status` lists the addresses it connects from), then run `deplane redis import` again.

### import_failed

The import stopped with an error. The message says what went wrong, for example that the database is bigger than a Deplane database, or that the source was unreachable for too long.

Fix: fix the cause named in the message, then run `deplane db import` again. The database made for the import stays; delete it with `deplane db destroy NAME`. If the message shows two SQL lines, run them on the source database: Deplane could not reach it to remove its replication slot and publication.

From `deplane redis import`, the copy or the file's load stopped; the message says why (its own code is in this list, for example [too_big](#too_big)). The new Redis stays, empty; delete it with `deplane redis destroy NAME`.

### import_finish_refused

`deplane db import finish` checked the source and the new database and changed nothing, so the import is syncing again. The message says why: the schema of the source changed, the new database had not caught up, or a table has a different number of rows on each side, which usually means something is still writing to the source.

Fix: stop every writer to the source, fix what the message says, and run `deplane db import finish` again. If the schema changed, cancel the import and import again after the change.

### import_mode_unavailable

The check found that the import mode you chose cannot work for this database. The message lists what the check found, for example that `wal_level` is not `logical`, or that a table has no primary key or replica identity, for a live import.

A copy of one of your Deplane databases is always copy mode: Deplane databases do not run `wal_level = logical`.

Fix: fix what the message lists on the source database and check it again, or choose copy mode, which needs only read access.

### import_not_possible

The check found that neither a copy nor a live import of this database can work. The message lists what it found, for example an extension Deplane does not have that an object depends on.

Fix: fix what the message lists on the source database, then run `deplane db import` again.

From `deplane import heroku`, this means the check found the Heroku database but no way to copy it, and nothing was created. (A Postgres version Deplane does not import is [source_too_new](#source_too_new).)

From `deplane redis import`, the check found that this Redis or file cannot be imported, for example that it holds more than 150 MB of data, runs in cluster mode, or that the file is too new. The CLI prints the reasons and cancels the check. Fix: fix what the message lists, then run `deplane redis import` again.

### import_not_ready

The import is not in a state that allows what you asked: only a checked import can be started, only a live import that is copying changes can be finished, and an import that is done, cancelled or failed can no longer be cancelled. The message names the state it is in.

Fix: reload the import to see where it is. A check takes up to 5 minutes, and a checked import that is not started within an hour expires: check the database again.

For a Redis import, only a checked import can be started, and an import that is done, cancelled, failed or expired can no longer be cancelled.

### import_slow

`deplane db import` stopped waiting: the import stayed in the same state for longer than the CLI follows it (10 minutes for a check, a little over 4 hours for a copy, 30 minutes for a finish, 10 minutes for a cancel). The import itself keeps going.

Fix: see where it is with `deplane db import status`.

`deplane redis import` follows a check for 10 minutes and a copy or a file's load for 45 minutes. Fix: see where it is with `deplane redis import status`.

### importer_config

The import could not start because Deplane gave it incomplete settings. This is a problem on our side, not with your database.

Fix: cancel the import and start it again. If it keeps happening, email support@deplane.io.

### importer_internal

The import stopped on an unexpected error inside Deplane. Your database was not changed by it.

Fix: cancel the import and start it again. If it keeps happening, email support@deplane.io with the import's ID.

### imports_unavailable

Database imports are switched off on Deplane right now, so no import can be checked or started. Imports already running can still be finished or cancelled.

Fix: try again later. If you need to move a database now, email support@deplane.io.

Redis imports answer the same way when they are switched off, and loading an RDB file also when Deplane's backups are. Fix: try again later, or copy the Redis from its URL.

### impersonation_read_only

A Deplane administrator viewing a team (for support) can only look: every change is refused while viewing.

Fix: Stop viewing as the team from the red banner.

### instances_on_cron

A cron job was given an instance count. Each run of a cron job is one instance.

Fix: leave instances out for a cron job; set its schedule instead.

### internal

Something went wrong on our side, or the CLI hit an unexpected problem.

Fix: try again, with `--debug` for details. If it keeps happening, email support@deplane.io with the request ID.

### invalid_alert_channel

The alert channel's kind or name is not valid.

Fix: Use slack, discord or webhook (email is not delivered yet), and a name of at most 60 characters.

### invalid_alert_settings

An alert threshold is out of range: the error rate is between 0.1% and 100%, the response time between 100 and 60000 ms.

Fix: Pick a value in range, like 5% or 2000 ms.

### invalid_alert_target

The webhook address is not valid for its kind: Slack needs https://hooks.slack.com/services/…, Discord https://discord.com/api/webhooks/…, and a webhook a public https:// address.

Fix: Copy the URL again from Slack, Discord, or your endpoint.

### invalid_api_url

`DEPLANE_API_URL` is not a valid URL.

Fix: set it to a URL such as `https://api.deplane.io`, or unset it.

### invalid_app_name

App names are 3 to 40 characters: lowercase letters, digits, and single hyphens, starting with a letter and not ending with a hyphen.

Fix: pick a name like `my-app`.

### invalid_arguments

An AI tool called a Deplane tool with arguments it cannot use, such as a missing app name or a malformed build ID.

Fix: the tool checks the tool's input schema and calls it again; list apps with list_apps and builds with builds.

### invalid_auto_rollback

`deplane config --auto-rollback` got a value other than on or off.

Fix: use `deplane config --auto-rollback on` or `deplane config --auto-rollback off`.

### invalid_autoscale

The autoscaling ceiling is not valid: it must be more than the number of instances and at most 1000, and a stopped app cannot autoscale.

Fix: set `max_instances` above `instances` (for example `deplane scale 1 --max 5`), or 0 to turn autoscaling off.

### invalid_branch

The branch name is not valid.

Fix: Use the branch's name as GitHub shows it, for example `main`.

### invalid_category

An abuse report's category is not one of the allowed ones.

Fix: use `phishing`, `malware`, `spam`, `csam`, `copyright`, `illegal`, `template` (a community template), or `other`.

### invalid_client

Deplane does not know the AI tool that sent this request. Its registration may have been removed.

Fix: connect Deplane again from the AI tool, which registers it afresh.

### invalid_client_metadata

The AI tool sent registration details Deplane cannot accept: unreadable JSON, text with NUL characters, or a client that needs a secret.

Fix: Deplane supports public clients only. Register with `token_endpoint_auth_method` set to `none` and send a single JSON object.

### invalid_code

The authenticator code is not correct.

Fix: enter the current 6-digit code from your authenticator app.

### invalid_command

A worker's, cron job's, release command or run's command is empty, too long, or spans lines. `deplane run` with nothing after `--` is also this error.

Fix: give one line of at most 1000 characters, for example `node worker.js`. It runs through the image's shell (`/bin/sh -c`). For `deplane run`, put the command after `--`: `deplane run -- python manage.py seed`.

### invalid_company

The company name in an access request is longer than 200 characters.

Fix: shorten the company name.

### invalid_config

`deplane.toml` is not valid: it is not TOML, has an unknown setting, or has a bad value.

Fix: fix the line the message names. `deplane.toml` knows `app` and, under `[service]`, `port` (1 to 65535), `instances`, `size` (`small`, `medium`, or `large`), and `health_check` (a path starting with `/`). Or delete the file and run `deplane launch`.

### invalid_conversation

The conversation sent to the assistant is not valid: it must end with your question, and each message needs a role and text.

Fix: Ask again; the dashboard and `deplane ask` send it correctly.

### invalid_database_name

Database names are 3 to 30 characters: lowercase letters, digits and single hyphens, starting with a letter.

Fix: pick a name such as `main`, `orders`, or `analytics-db`.

### invalid_domain

The hostname is not a public domain name Deplane can route.

Fix: enter a hostname such as `www.example.com` or `example.com`, without `https://` or a path.

### invalid_drill

A drill result was malformed: its start must come before its end, neither in the future, with a summary of at most 8000 characters.

Fix: send the result `infra/dr/drill.sh` sends.

### invalid_email

The email address is not valid.

Fix: enter an address like `you@company.com`.

### invalid_entitlements

An admin sent plan limits with an unknown key or a bad value.

Fix: use the keys and value types shown by `GET /v1/admin/plans`.

### invalid_exclude_schemas

The list of schemas to leave out of an import is not valid. It can hold at most 100 schema names, and each one is 1 to 63 bytes, with no commas, no NUL characters, and no spaces or tabs at either end.

Fix: give each schema's exact name as one entry, for example `audit` or `old_data`.

### invalid_files

An AI tool sent files to deploy that Deplane cannot pack: no files, more than 5,000, more than 25 MB in all, a path that is not a clean relative path (absolute, or with `..`, `//` or a backslash) or that appears twice, or content marked base64 that is not valid base64.

Fix: send each file as {path, content, encoding}: a relative path, utf8 or base64 content.

### invalid_findings

The watcher's findings were malformed: at most 50 checks, each with a lowercase name and a detail of at most 500 characters.

Fix: send `{"findings":[{"check":"canary","detail":"…"}]}`.

### invalid_flag

A flag got a value it does not take, or a value out of range. For example, `--json=true`, or `--expires-in-days 500`.

Fix: use the flag as the message says. `deplane help` lists the flags.

`--check` works only with the `deplane import` commands (`heroku`, `render`, `railway`, `compose`, `fly`, `vercel`, `netlify` and `cpanel`) and `deplane domains switch`; `--source` only with `deplane import heroku`, `render`, `railway`, `fly`, `vercel` and `netlify`; `--prefix` only with `deplane import compose`; `--host`, `--user`, `--site`, `--backup`, `--db-dump`, `--cutover` and `--replace-live` only with `deplane import cpanel`; `--adopt` and `--prune` only with `deplane stack plan` and `deplane stack apply`; and `--format` only with `deplane stack export`. Any other command refuses them, so a command is never taken for a dry run.

### invalid_grant

The sign-in code or refresh token is wrong, expired, or was already used. If a code or refresh token is used twice, Deplane ends that connection as a precaution.

Fix: connect Deplane again from the AI tool.

### invalid_health_check

The health check is not a valid path.

Fix: use a path that starts with `/` and has no spaces, for example `/healthz`, or leave it out for a TCP check.

### invalid_image

The image reference is not valid.

Fix: write it as `[registry/]name[:tag]` in lowercase, with no spaces or special characters, for example `nginxinc/nginx-unprivileged:1.27-alpine`. To pin an exact version, end it with `@sha256:` and 64 hex characters.

### invalid_image_digest

A release was given an image reference that is not a sha256 digest.

Fix: pass a digest like `sha256:` followed by 64 hex characters. Releases made by `deplane deploy` always have one.

### invalid_instances

The number of instances is not a whole number of 0 or more.

Fix: run `deplane scale 2`, or `deplane scale 0` to stop the app.

### invalid_json

The request body is not valid JSON for this endpoint, has unknown fields, or contains more than one object.

Fix: check the request format at https://api.deplane.io/v1/openapi.yaml and send exactly one JSON object.

### invalid_kind

An admin instance list was filtered by a kind of microVM that does not exist.

Fix: use `kind=app`, `kind=worker`, `kind=database`, or `kind=build`.

### invalid_limit

A list request asked for too few or too many entries, or `deplane logs --limit` was not a number of lines from 1 to 5000.

Fix: use a `limit` from 1 to 200 for a list, for example `?limit=50`; for kept logs, `--limit` from 1 to 5000, for example `deplane logs --since 1d --limit 2000`.

### invalid_log_time

`deplane logs --since` or `--until` was not a time Deplane reads.

Fix: give an age such as `30m`, `3h` or `3d`, a UTC day such as `2026-11-03`, or a time such as `2026-11-03T14:00:00Z`.

### invalid_mode

A passkey or GitHub sign-in was started with an unknown mode.

Fix: reload the page, or start again from the sign-in page.

For an import, the mode must be `copy` or `live`; `deplane db import --mode` takes the same two.

Fix: start the import with `copy`, or with `live` to keep copying changes until you finish.

### invalid_name

The name in an access request is empty or longer than 200 characters.

Fix: enter your name or your company's name.

### invalid_payload

The webhook's body is not valid JSON.

Fix: Only GitHub sends webhooks to Deplane; nothing to do.

### invalid_period

A metrics request asked for a period Deplane does not chart.

Fix: use `period=1h`, `period=24h`, `period=7d`, or `period=30d`.

### invalid_plan

The plan does not exist or is not offered any more.

Fix: Pick one of the plans listed in the admin console's Settings.

### invalid_port

The port is not between 1 and 65535.

Fix: use the port your app listens on. Deplane also sets it as `PORT`.

### invalid_postgres_version

The Postgres version asked for a new database is not one Deplane runs. Versions are major version numbers: `17` or `18`.

Fix: pass `--version 17` or `--version 18`, or leave it out for 17.

### invalid_private_network

`--private-network` was given a value other than `on` or `off`.

Fix: use `deplane config --private-network on` or `deplane config --private-network off`.

### invalid_process_kind

A process must be a worker or a cron job.

Fix: use kind `worker` (always running) or `cron` (on a schedule).

### invalid_process_name

Process names are 2 to 22 characters: lowercase letters, digits and hyphens, starting with a letter. `web` is the app itself, and `release` and names starting with `run-` are kept for the release command and `deplane run`.

Fix: pick a name such as `worker`, `emails`, or `nightly-report`.

### invalid_pull_request

A previews command or request did not name a pull request by its number.

Fix: pass the number, such as `deplane previews build 21`. `deplane previews` lists the live previews and the pull requests waiting for one.

### invalid_range

A usage request asked for a range Deplane does not report.

Fix: use `range=24h`, `range=7d`, `range=30d`, `range=month`, or `range=prev_month`. A server's history in the admin console takes `range=24h` or `range=7d`.

### invalid_recovery_code

The recovery code is not correct or was already used.

Fix: check the code and try again. Each recovery code works once.

### invalid_redirect_uri

The return address is not allowed. It must be https, or http on a loopback address (localhost or 127.0.0.1), have no fragment, and match one the AI tool registered.

Fix: update the AI tool and connect again. If you build the tool, register only addresses that meet these rules.

### invalid_region

The region is not available.

Fix: use region `fra`, or leave the region out.

### invalid_replace

A pull request was asked to replace its own preview.

Fix: give `--replace` the number of another pull request that has a preview.

### invalid_report_status

An admin passed a report status that does not exist.

Fix: for `deplane admin abuse list`, use `open`, `investigating`, `actioned`, `rejected`, or `all`. For `deplane admin abuse resolve`, use `investigating`, `actioned`, or `rejected`.

### invalid_report_url

An abuse report's URL is missing or is not a valid `http` or `https` address.

Fix: paste the full address of the page you are reporting, for example `https://example-app.deplane.app/login`.

### invalid_request

The connection request is missing something or is malformed. Deplane requires PKCE with the `S256` method.

Fix: update the AI tool and connect again. If you build the tool, send a `code_challenge` made with `S256` and a `state` of at most 500 characters.

### invalid_restore_time

The restore time is not a time Deplane understands.

Fix: use `latest`, a time like `2026-10-15T14:31:20Z`, or in the CLI `2026-10-15 16:31` (your local time) or `-10m` (ten minutes ago).

### invalid_role

A team role is `member` or `owner`.

Fix: use `member` (deploys and manages apps) or `owner` (also invites and removes people).

### invalid_root_dir

The root folder is not a plain path inside the repository.

Fix: Use a path like `apps/web` (no `..`), or leave it empty.

### invalid_schedule

The cron schedule is not valid.

Fix: use five fields in UTC (minute, hour, day of month, month, day of week), for example `*/15 * * * *` or `0 3 * * *`, or `@hourly`, `@daily`, `@weekly`, `@monthly`.

### invalid_scope

There is no such secret kind.

Fix: use `runtime` (the default) or `build`. In the CLI, pass `--build` for build secrets.

### invalid_secret

An argument to `deplane secrets set` is not `NAME=VALUE`.

Fix: pass each secret as `NAME=VALUE`, for example `deplane secrets set DATABASE_URL=postgres://...`.

### invalid_secret_name

Secret names use capital letters, digits, and underscores, and do not start with a digit.

Fix: rename it, for example `DATABASE_URL`. See [Secrets](secrets.md#names).

### invalid_secret_value

A secret value contains a NUL byte, which environment variables cannot hold.

Fix: encode the value, for example as base64.

### invalid_setting

The value is not valid for that setting.

Fix: Check the value and try again.

### invalid_signature

A webhook's signature did not match Deplane's GitHub App secret.

Fix: Only GitHub can send webhooks to Deplane; nothing to do.

### invalid_size

There is no such size.

Fix: use `small`, `medium`, or `large`.

### invalid_sleep

Apps sleep after 5, 15 or 60 minutes without a request, or never; a stopped app cannot sleep. On Free, a stopped app keeps its sleep time, and setting 5 or 15 on it is allowed: it applies when the app starts.

Fix: use `deplane scale --sleep 15m`, or `--sleep off`.

### invalid_sort

An admin usage request asked to rank teams by something Deplane does not total.

Fix: use `sort=cpu`, `sort=memory`, `sort=bandwidth`, `sort=requests`, `sort=build`, or `sort=instances`.

### invalid_source

The upload is not a gzip-compressed tar archive, or it is damaged.

Fix: upload with `deplane deploy`, which packages the folder for you.

### invalid_source_url

The database URL for an import cannot be used. It must look like `postgres://USER:PASSWORD@HOST:PORT/DATABASE`: one host, a user, a password, and a database name. The only options accepted are `sslmode` (`disable`, `require`, `verify-ca` or `verify-full`) and `sslrootcert=system`. `verify-ca` and `verify-full` both check the server's certificate and host name against the system's trusted roots, and `sslrootcert=system` asks for the same, so it cannot go with `sslmode=disable`. The URL can be at most 2048 characters.

Fix: correct the URL. Encode special characters in the password (for example `@` as `%40`), and remove options such as `passfile`, `service`, or `options`. Deplane never repeats your URL or password in an error.

From `deplane redis import`, the Redis URL must be `redis://` or `rediss://`, with one host, an optional port (default 6379), an optional user name, a password, and an optional database number from 0 to 15 (`/0`), with no options after a `?`, at most 2048 characters. The CLI refuses anything else before it sends it, without repeating it. Fix: paste the Redis's own URL; for a link to an RDB file, use `deplane redis import --rdb-url`.

### invalid_stack

The stack label sent with an app's settings is not a short label.

Fix: send at most 40 letters, digits, spaces, and `. + # - /`, such as `Next.js` or `Python`. The CLI and dashboard send it for you.

### invalid_status

An admin passed an access request status that does not exist.

Fix: use `pending`, `approved`, or `denied`.

### invalid_tail

`--tail` is not a number of lines from 0 to 1000.

Fix: for example `deplane logs --tail 200`.

### invalid_team_name

A team name is 2 to 50 characters.

Fix: pick a name like Acme or Acme Engineering.

### invalid_text

The request contains a NUL character or text that is not valid UTF-8.

Fix: Remove the control characters and send it again.

### invalid_token_kind

A token kind other than `cli` or `ci` was requested.

Fix: use kind `ci` for automation. `deplane tokens create` does this for you.

### invalid_token_name

A token name must be 1 to 100 characters.

Fix: name the token after where it is used, for example `github-actions`.

### invalid_ttl

The token lifetime is out of range.

Fix: use 1 to 365 days, or leave it out for the default of 90 days.

### invalid_use_case

The use case in an access request is longer than 2000 characters.

Fix: shorten the description.

### invalid_version

The release version is not a positive number.

Fix: run `deplane releases` to see the versions, then `deplane rollback 3` or `deplane rollback v3`.

### invite_invalid

The invitation link was already used, revoked, or is older than 7 days.

Fix: ask the person who invited you for a new link.

### key_rejected

The service did not accept the API key.

Fix: Copy the key again from the service's console and paste it whole.

### key_unchecked

Deplane could not check the key with the service, so it was not saved.

Fix: Try again in a minute.

### kubernetes_unavailable

The API server cannot read the cluster, so the admin console cannot show servers.

Fix: set KUBECONFIG for deplane-api (operators).

### last_owner

A team needs at least one owner, so its last owner can neither be removed nor leave.

Fix: make someone else an owner first.

### layer_device_file

The built image contains a device file.

Fix: do not create device files in the image, for example with `mknod`. Deplane provides `/dev`.

### layer_path_traversal

The built image contains a path that points outside the image.

Fix: check the Dockerfile's `COPY` and `ADD` steps, and any archives they unpack, for paths with `..` in them.

### layer_setuid

The built image contains a setuid or setgid file outside the system folders, or replaces a system folder such as `/usr` or `/bin` with a link.

Fix: remove the setuid or setgid bit (`chmod u-s,g-s`) or install the program under `/usr/bin`. Keep `/usr`, `/bin`, `/sbin`, and `/usr/local/bin` as real folders.

### layer_too_large

A layer of the built image is larger than 2 GB.

Fix: make the image smaller. Leave build tools, caches, and data files out of the final stage.

### layer_unsupported

The built image has a layer type Deplane does not run.

Fix: build with a standard Dockerfile or without one. Foreign and zstd layers are not supported.

### limit_apps

Your organization has as many apps as its plan allows.

Fix: destroy an app you no longer need with `deplane apps destroy NAME`, or email support@deplane.io to raise the limit.

### limit_bandwidth

Your team's apps sent all the bandwidth its plan includes this month: what your apps send to visitors. On Free, your apps answer every visitor with a page that says "This site has reached its monthly bandwidth limit" (HTTP 503) until the 1st of next month (UTC). On paid plans, apps keep running and Deplane gets in touch. Deploys, builds, logs, databases, the dashboard and the CLI keep working. You see this page, not an error from the CLI or the API.

Fix: wait until the 1st (UTC), move to a larger plan, or email support@deplane.io to raise the limit. Your apps are back within about 10 minutes. See what you used on the Usage page or with `deplane usage`. See [Limits](limits.md).

### limit_build_minutes

Your organization used all its build minutes for this month.

Fix: wait until the 1st of next month (UTC), or email support@deplane.io to raise the limit.

### limit_databases

Your team has as many Postgres databases as its plan allows. Pull request preview databases do not count. A team moved to a smaller plan keeps the databases it has; only new ones are refused.

Fix: delete one you no longer need with `deplane db destroy NAME`, or email support@deplane.io to raise the limit.

### limit_domains

Your team has as many custom domains as its plan allows, counting every app. A team moved to a smaller plan keeps the domains it has; only new ones are refused. One app can also have at most 10 (see [too_many_domains](#too_many_domains)).

Fix: remove one you no longer use with `deplane domains remove HOSTNAME`, or email support@deplane.io to raise the limit.

### limit_instances

The change needs more instances, across all your apps, than your plan allows.

Fix: use fewer instances, scale down another app, or email support@deplane.io to raise the limit.

### limit_without_range

`deplane logs --limit` counts kept lines, so it needs `--since`, `--until` or `--search`.

Fix: add one, for example `deplane logs --since 1d --limit 2000`, or use `--tail N` for the running instances.

### limit_log_streams

Your organization already has as many live log streams open as its plan allows. A deploy that follows its build log counts too.

Fix: stop another `deplane logs -f` or a running deploy, then try again. A deploy still finishes without showing the log.

### limit_members

Your team has as many people as its plan allows. Open invitations count, since each can become a member. A team moved to a smaller plan keeps its members; only new invitations are refused.

Fix: remove someone with `deplane team remove EMAIL`, or revoke an open invitation in the dashboard, or email support@deplane.io to raise the limit.

### limit_memory

The change needs more memory, across all instances of all your apps, than your plan allows.

Fix: use a smaller size or fewer instances, scale down another app, or email support@deplane.io to raise the limit.

### limit_previews

Your plan does not include pull request previews. No preview is made, and the pull request gets a comment that says so. Previews made before the plan changed are kept.

Fix: previews come with Hobby and larger plans. Email support@deplane.io to change your plan, or turn previews off in the app's GitHub settings.

### limit_sleep

On Free, apps always sleep when idle: after 5 or 15 minutes without a request, never 60 minutes or never. Asking for sleep off or 60 minutes is refused. So is starting or growing an app (more instances, a larger size, a higher autoscale maximum, or 0 to more) whose sleep would be off or 60 minutes, which happens with an app from before its team moved to Free. Scaling down and stopping always work and keep the app's setting.

Workers run all the time, so Free does not include them: adding a worker, or starting or growing one, is refused too. Workers from before a move to Free keep running and can be scaled down or removed. Cron jobs are allowed.

Fix: add `--sleep 15m` or `--sleep 5m`, for example `deplane scale 2 --sleep 15m`. For scheduled work, use a cron job. Apps can stay on, and workers come, with Hobby and larger plans; email support@deplane.io to change your plan.

### limit_size

Your plan does not include this instance size. A run (`deplane run --size`) can use any size up to your plan's largest.

Fix: use a size your plan includes (the message lists them), or email support@deplane.io.

### log_range_empty

`deplane logs --until` is not after `--since`, or both are before the oldest day your plan keeps.

Fix: pick an `--until` later than `--since`, within the days your plan keeps ([Limits](limits.md#logs)).

### log_read_too_slow

A read of kept logs took more than 40 seconds: the range holds too many lines to go through at once.

Fix: ask for a shorter range, for example `deplane logs --since 2h`, or add `--search`.

### log_range_too_long

One read of kept logs covers at most 31 days.

Fix: ask for 31 days or less at a time, for example `deplane logs --since 60d --until 30d`, then `--since 30d`.

### logs_not_kept

The logs past the running instances are not kept for your team: kept logs are not switched on for it yet, or your plan keeps none.

Fix: run `deplane logs` without `--since`, `--until` or `--search` for the recent lines of each running instance. Kept logs are being switched on team by team; plans keep them from 7 days on Free to 365 days on Enterprise.

### logs_unavailable

Logs are not available right now.

Fix: try again in a few minutes. If it keeps happening, email support@deplane.io.

### magic_link_invalid

The sign-in link is invalid, expired, or already used.

Fix: request a new link on the sign-in page. Links work once and expire after 15 minutes.

### missing_database

A `deplane db` command needs the database it acts on.

Fix: pass its name, for example `deplane db attach main --app shop`. `deplane db` lists them.

### missing_delivery

A GitHub webhook arrived without its X-GitHub-Delivery ID, so Deplane refused it. GitHub always sends one; a request without it is not from GitHub.

Fix: Nothing to do if you use the Deplane GitHub App. Custom senders must forward GitHub's headers unchanged.

### missing_domain

A `deplane domains` command needs the domain it acts on.

Fix: pass it, for example `deplane domains add www.example.com`. `deplane domains` lists the app's domains.

### missing_email

A `deplane team` command needs an email address.

Fix: pass it, for example `deplane team invite colleague@company.com`.

### missing_flag_value

A flag that needs a value was given none.

Fix: pass it as `--flag VALUE`, for example `--tail 200`.

### missing_id

The command needs an ID.

Fix: pass it, for example `deplane tokens revoke ID` or `deplane disks restore APP BACKUP-ID`. `deplane tokens list` and `deplane disks backups APP` show the IDs.

### missing_name

The command needs a name. `deplane db import` needs `--name` when no terminal is attached to ask for one.

Fix: for example `deplane apps destroy my-app` or `deplane tokens create github-actions`.

### missing_process

A `deplane processes` command needs the process it acts on.

Fix: pass its name, for example `deplane processes scale worker 2`. `deplane processes` lists them.

### missing_reason

A suspension needs a reason, and so do rejecting a community template version and delisting a listing (the publishing team sees it).

Fix: pass `--reason TEXT`, for example `deplane admin suspend-app NAME --reason "Phishing, report abr_..."`.

### missing_report

The command needs an abuse report ID.

Fix: pass it, for example `deplane admin abuse show ID`. `deplane admin abuse list` shows the IDs.

### missing_request

The command needs an access request's email or ID.

Fix: for example `deplane admin approve dev@example.com`.

### missing_target

`deplane admin unsuspend` needs exactly one target.

Fix: pass `--app NAME` or `--org SLUG`, not both.

### missing_team

`deplane team switch` needs the team's slug.

Fix: find it with `deplane teams`.

### missing_url

`deplane db import` got no database URL: nothing was typed at the prompt, or nothing was piped in.

Fix: run `deplane db import` in a terminal and paste the URL when asked, or pipe it in: `printf '%s' "$SOURCE_URL" | deplane db import --name NEW --yes`.

`deplane redis import` got no Redis URL (or, with `--rdb-url`, no file link) the same way. Fix: run it in a terminal and paste it when asked, or pipe it in: `printf '%s' "$REDIS_URL" | deplane redis import --name NEW --yes`.

### network_error

The CLI could not reach the Deplane API, or the connection broke.

Fix: check your internet connection and run the command again. Set `DEPLANE_API_URL` if you use a different API.

### no_alert_destination

A platform admin sent a test to the operator alert destinations, but none is set up: no team a platform admin owns has an alert channel.

Fix: in a team you own as a platform admin, open Alerts and add a Slack, Discord or webhook channel, then send the test again from Admin, Alerts.

### no_app

No app is selected. There is no `deplane.toml` here and no `--app` flag.

Fix: pass `--app NAME`, or run the command in a folder with a `deplane.toml`. `deplane launch` creates one.

### no_backup_yet

The database has no finished full copy yet, so it cannot be restored.

Fix: the first copy finishes a few minutes after a database is created; try again soon.

### no_builds

An AI tool asked to wait for a deploy of an app that has never been built.

Fix: deploy it with deploy_files or deploy_github first.

### no_config_dir

There is no keychain and no config folder to store your login in.

Fix: set `DEPLANE_TOKEN` instead.

### no_earlier_release

There is no earlier release that ran successfully, so `deplane rollback` has nothing to go back to.

Fix: run `deplane releases` and roll back to a specific version with `deplane rollback VERSION`.

### no_import

`deplane db import finish` or `cancel`, run without an ID, found no import in progress, or `status` found no import at all. (With an ID that is not your team's, the API answers `not_found` instead.)

Fix: start one with `deplane db import`. `deplane db import status` shows the newest import, active or not.

`deplane redis import status` and `cancel` say the same of Redis imports. Fix: start one with `deplane redis import`.

### no_passkey

There is no passkey on this account yet.

Fix: set up a passkey first, from your account page.

### no_pending_request

There is no pending access request for that email.

Fix: list them with `deplane admin requests`.

### no_disk_space

There is no free disk space on the platform right now, so the disk was not added. We have been alerted.

Fix: try again later or contact support (support@deplane.io). See [Disks](disks.md).

### no_progress

The live import stopped because its replication slot on your database had not moved for an hour while your database kept writing its log. A slot that does not move keeps the log from being removed, so the source's disk fills; the import was stopped to protect it, and its slot was removed.

Fix: start a new import. If it happens again, email support@deplane.io with the import's ID.

### no_releases

This app has no releases yet, so there is nothing to roll back to.

Fix: deploy it first with `deplane deploy`.

### no_secrets

No secrets or secret names were given.

Fix: run `deplane secrets set NAME=VALUE` or `deplane secrets unset NAME`.

### no_team

This account is not in a team any more.

Fix: Ask a team owner to invite you again, or request access at /beta.

### no_team_login

There is no login on this computer for the team you named with `--team`, `DEPLANE_TEAM` or `deplane team switch`.

Fix: run `deplane login --team SLUG`, then try again.

### not_a_member

The address is not in your team.

Fix: run `deplane team` to see the members.

### not_caught_up

Finish waited for the new database to have every change from your database, and it did not get there within 10 minutes: either it was still behind, or changes kept arriving, which means your app was still writing to the source. Finish changed nothing, and the import keeps syncing.

Fix: stop every write to the source database, then finish again.

### not_found

The resource does not exist, or you do not have access to it. Deplane answers the same way in both cases, so nobody can find out what other organizations have.

Fix: check the name or ID. `deplane apps` lists your apps.

### not_logged_in

You are not logged in.

Fix: run `deplane login`, or set `DEPLANE_TOKEN`.

### not_signed_in

Your sign-in session in the browser has ended.

Fix: sign in again.

### not_suspended

An admin tried to unsuspend an app or organization that is not suspended.

Fix: nothing to do. Check the name or slug.

### nothing_to_change

An app settings change had no port, health check, release command, automatic rollback or private network setting.

Fix: set the port and health check in `deplane.toml` under `[service]`, then run `deplane deploy`. Turn automatic rollback on or off with `deplane config --auto-rollback on|off`, and the private network with `deplane config --private-network on|off`.

### nothing_to_redeploy

The app has never been built, so there is no source to build again.

Fix: deploy it first with `deplane deploy`, from the dashboard, or by connecting GitHub.

### nothing_to_scale

`deplane scale` was given neither a number of instances nor a size.

Fix: run `deplane scale 2` or `deplane scale --size medium`.

### nothing_to_switch

The database you switch from is not attached to any app, or it is the same database.

Fix: pass the original database with `--from`, or attach the restored database to an app with `deplane db attach`.

### oauth_not_allowed

Only you, signed in to the dashboard, can connect an AI tool. CLI logins, CI tokens, AI tool connections, and admin views of a team cannot approve a connection.

Fix: sign in to the dashboard yourself and try again.

### oauth_request_expired

This connection request expired after 10 minutes or was already answered.

Fix: start connecting Deplane again from your AI tool.

### oauth_unavailable

Connecting AI tools is not set up on this server, so the OAuth endpoints and the connections list are off.

Fix: use a CI token from the Tokens page instead.

### ops_not_allowed

An ops token tried something other than deploying the operations team's canary.

Fix: use your own login for anything else.

### origin_not_allowed

A browser on another website sent an access request. The API takes them from a browser only on the Deplane site.

Fix: request access on the Deplane site's [beta page](https://deplane.io/beta), or email support@deplane.io. The CLI and scripts that send no `Origin` header are not affected.

### outside_backup_window

The time is outside the database's restore window. The message lists the window, or windows when there are gaps.

Fix: pick a time inside it, or restore the latest moment.

### owners_only

Only the team's owners can invite or remove people.

Fix: ask an owner of the team.

### passkey_ceremony_missing

No passkey request is in progress in this browser.

Fix: reload the page and try again.

### passkey_failed

The passkey could not be verified.

Fix: try again with a passkey registered to this account on this site.

### passkey_required

This needs your passkey or security key. Admins confirm only with a passkey, and approving a CLI login needs one.

Fix: confirm with your passkey or security key, then try again.

### passkeys_unavailable

Passkeys are not set up on this server.

Fix: email support@deplane.io.

### payload_too_large

The webhook's body is larger than 10 MB.

Fix: Only GitHub sends webhooks to Deplane; nothing to do.

### paused_on_worker

A worker was to be paused. Only cron jobs can be paused: a pull request environment's cron jobs keep their schedule and do not run.

Fix: scale the worker to 0 instances to stop it.

### postgres_version_unavailable

Deplane runs that Postgres version but does not offer it for new databases yet (Postgres 18 is offered once its rollout is done). Nothing was created.

Fix: leave the version out to create the database on Postgres 17, or try again later.

### preview_database_needs_previews

Preview databases were turned on with pull request previews off. A preview database belongs to a preview, so there would be nothing to give it to. (HTTP 422)

Fix: Turn previews on, or leave preview databases off.

### preview_private_network

The private network was turned on for a pull request preview. A preview never reaches the team's other apps privately, and they never reach it, so a pull request cannot talk to production.

Fix: turn the private network on for the app itself with `deplane config --private-network on`.

### preview_not_found

The pull request has no live preview to remove or replace.

Fix: list the live previews with `deplane previews`, or in the dashboard's Pull request previews card.

### preview_not_waiting

The pull request is not waiting for a preview. A pull request waits once it was refused one (the app's previews, the plan's room or the servers were full) or its preview was removed or replaced. One that already has a preview, or that Deplane never refused, is not on the list.

Fix: list the waiting pull requests with `deplane previews`. For a pull request that is not there, push to it: the push makes its preview, or puts it on the list.

### preview_slots_full

The app already has 3 previews, so a waiting pull request can only get one by replacing one of them. The message lists them.

Fix: choose one to replace, `deplane previews build PR --replace PR`, or remove one first with `deplane previews remove PR`. In the dashboard, Build preview asks which one to replace.

### previews_off

Previews are off for the app, so there are none to build.

Fix: turn previews on in the app's GitHub settings. Pull requests then get previews on their next push.

### private_network_sleep

Sleep and the private network were asked for together. A sleeping app wakes only for public requests, so it cannot answer the team's other apps. Turning the private network on is refused while sleep is on, and sleep is refused while the private network is on. Autoscaling is not affected.

Fix: to turn the private network on, first turn sleep off with `deplane scale --sleep off`. To let the app sleep, first turn the private network off with `deplane config --private-network off`. On Free, apps always sleep ([limit_sleep](#limit_sleep)), so the private network needs Hobby or a larger plan.

### private_network_too_many

The private network was turned on for a team with 2000 apps or more. The private network lists every other app of the team, and the list has a ceiling of 2000. Previews do not count.

Fix: destroy apps the team no longer uses, or email support@deplane.io.

### private_registry_unsupported

The image is on a registry Deplane cannot pull from. Only images that anyone can pull from a public registry (Docker Hub, GHCR and similar) work. Private registries, Deplane's own registry, names ending in `.internal`, `.local` or `.localhost`, `localhost`, and addresses on a private network are refused.

Fix: use a public image, or deploy your code with `deplane deploy` instead.

### project_file_taken

The folder has an `app.toml` that is not this CLI's project file, so `launch` would overwrite another tool's file. Nothing was created.

Fix: move or rename that `app.toml`, or pass `--app NAME` to deploy an existing app.

### process_exists

The app already has a worker or cron job with that name.

Fix: pick another name, or change the existing process.

### quota_exceeded

A general quota was reached. Like the `limit_` codes, the CLI exits with code 6.

Fix: follow the fix in the message, or email support@deplane.io to raise the limit.

### railpack_plan_failed

Deplane could not work out how to build this project without a Dockerfile. The message shows the last lines of the build planner's output.

Fix: add a Dockerfile, or follow the messages in the build log. Check that your project files, such as `package.json` or `requirements.txt`, are in the folder you deploy.

### rate_limited

Too many requests in a short time. The response has a `Retry-After` header. For the dashboard's **Import from another platform**, it is 20 lists, checks and imports an hour per person and 100 a day per team, counted across every Deplane API server.

Fix: wait a minute and try again. See the rate limits in [Limits](limits.md#rate-limits).

### read_only_view

You are viewing this team read-only, as support, so you cannot switch teams, join a team or leave one.

Fix: stop viewing the team first.

### registry_unavailable

The built image could not be checked because our image storage was unavailable.

Fix: run `deplane deploy` again. If it keeps happening, email support@deplane.io.

### release_command_on_preview

A release command was set on a pull request preview. A preview runs the release command of the app it belongs to, against its own database, and its own would be replaced at its next build.

Fix: set the release command on the app itself with `deplane config --release-command "<command>" --app <app>`.

### release_not_found

That release version does not exist for this app.

Fix: run `deplane releases` to see the versions.

### report_too_long

A field of an abuse report is longer than allowed.

Fix: shorten the details. Attach evidence by email to abuse@deplane.io instead.

### reserved_database_name

Database names cannot end in `-config`, `-failover`, `-sync` or `-failsafe`: Deplane uses those endings for each database's own records.

Fix: pick another name, such as `main-db` or `orders`.

### reserved_domain

The hostname is one of Deplane's own domains.

Fix: every app already has an address on Deplane's domain. Connect a domain you own instead.

### restore_before_import_end

This database was a live import, and you asked to restore it to a moment before that import ended. A copy from then would still be copying from the source, so Deplane does not make one. The message gives the earliest moment you can pick (UTC).

Fix: pick that moment or a later one, or use `latest`. Copy imports do not limit restores.

### restore_running

A restore of this disk is already under way.

Fix: wait for it to finish; the app starts again when it is done. A backup cannot start, and the disk cannot be destroyed, during a restore.

### run_busy

Your team already has 2 release commands and runs under way, the most it runs at once. A release command counts while a deploy runs it, and a run counts from the moment it starts until it ends.

Fix: wait for the release command or run under way to end, then try again. A run that starts while a new release takes the last slot waits, shown as "Waiting for a free slot", and starts once one ends.

### run_limit

There are already too many runs under way: an app has at most 2 at once, and a team at most 5.

Fix: wait for one to end, or cancel one, then try again.

### run_no_release

The app has no release that rolled out, so there is nothing to run the command in. A run uses the app's live release: its code, variables and database access.

Fix: deploy the app with `deplane deploy`, then run the command once the app is live.

### run_on_preview

Pull request previews cannot run commands.

Fix: run the command on the app itself with `deplane run --app <app> -- <command>`.

### run_rate_limited

Your team started 30 runs in the last hour, the most Deplane allows. Runs count however they ended.

Fix: try again later: the limit counts the last hour. If you need more, email support@deplane.io.

### run_timeout

`deplane run` followed a run for more than two hours and stopped. A run waits at most an hour for a free slot and then runs for at most an hour, so it ends on its own soon after.

Fix: look at the run's output with `deplane logs --process run_ID`, and start it again if it did not finish. For work that takes longer than an hour, use a [worker or cron job](workers.md).

### search_too_long

`deplane logs --search` takes at most 200 characters.

Fix: search for a shorter, distinctive part of the line.

### schedule_on_worker

A worker was given a schedule. Workers always run.

Fix: leave the schedule out, or create a cron job instead.

### schema_changed

The schema of your database changed after the import copied it: a table was added, dropped, or changed (a column, its type, a primary key or a replica identity). Live imports copy rows, not schema changes, so the new database cannot follow, and Finish is refused. The message names up to five tables.

Fix: start a new import after the change. To keep the downtime short, make schema changes before you import, or after you finish.

### second_factor_locked

Too many wrong authenticator or recovery codes. Codes are locked until the time in the message.

Fix: use your passkey, or try again after that time.

### secret_name_reserved

`PORT` and names starting with `DEPLANE_` are set by Deplane. A [variable group](variable-groups.md) also cannot hold `DATABASE_URL`, `REDIS_URL`, `MYSQL_URL`, `CLICKHOUSE_URL` or the cPanel import's `SITE_IMPORT_*` variables, which belong to one app.

Fix: pick another name.

### secret_not_found

You tried to remove secrets that are not set. Nothing was changed.

Fix: run `deplane secrets list` to see the names. For build secrets, pass `--build`.

### secret_too_large

A secret value is larger than 32 KB.

Fix: store large files elsewhere and put their location in the secret.

### secrets_too_large

Together, the app's secrets of this kind would be larger than 256 KB, a [variable group](variable-groups.md)'s would be, or an app's own and its groups' would be larger than 512 KB.

Fix: remove secrets you no longer need with `deplane secrets unset NAME` or `deplane groups unset GROUP NAME`, or detach a group.

### session_missing

Your sign-in session in the browser has ended.

Fix: reload the page and try again.

### slot_lost

The live import stopped because its replication slot on your database is gone: someone dropped it, or the database gave it up because it held more log than `max_slot_wal_keep_size` allows. Without it, the changes made since cannot be copied.

Fix: start a new import. If the source has `max_slot_wal_keep_size` set, make sure it leaves room for the time the import needs.

### source_address_blocked

The database host in an import URL is a private or reserved IP address: for example `10.x.x.x`, `192.168.x.x`, `127.0.0.1`, or `169.254.x.x`. Deplane connects to your database from the internet and does not connect to addresses on private networks.

Fix: use a public host name or IP address that is reachable from the internet, and allow connections to it in the firewall of the database's host.

### source_auth_failed

The database you are importing from refused the user name or password in the URL. Deplane never repeats the password in an error.

Fix: check the user and password, and encode special characters in the password (for example `@` as `%40`). Some providers need a different user or port for outside connections; use the connection string they give for direct connections.

### source_busy

The import gave up because a table on the database you are importing from is locked by another session, or a query took too long. The check and the copy wait at most a few seconds for a lock, so that your application never queues behind them, or behind a migration that waits for them.

Fix: try again when the long-running migration, `VACUUM FULL`, or other locking work on the source has finished.

### source_database_missing

The server you are importing from has no database with the name in the URL.

Fix: put the right database name after the last `/` of the URL. Names are case-sensitive.

### source_database_unavailable

The database you asked to copy (`deplane db copy`, or **Copy to a new database**) is not available right now: it is still being created, restoring, failed, or being deleted. The message says which.

Fix: wait until `deplane db` shows it available, then copy it again.

### source_mismatch

The uploaded source does not match the build that was queued for it.

Fix: run `deplane deploy` again. If it keeps happening, email support@deplane.io.

### source_newer_than_target

The import asked for a new database on an older Postgres major version than the source's, for example `--version 17` for a Postgres 18 source. A dump cannot be restored into an older major version, so nothing was created.

Fix: leave the version out (the import then picks the source's own major, such as 18), or ask for the source's major or a newer one: `deplane db import --version 18`.

### source_too_large

The project is larger than the upload limits: 100 MB compressed or 2 GiB uncompressed.

Fix: add build output, dependencies, and large data files to `.dockerignore` or `.gitignore`, then deploy again.

For an import, the database you are importing is larger than 5 GB (the size Postgres reports for it, in GB of 1000³ bytes). Deplane imports databases up to 5 GB.

Fix: import a smaller database. To move a larger one, email support@deplane.io.

### source_too_many_files

The project has more than 200,000 files.

Fix: add dependencies and build output, for example `node_modules`, to `.dockerignore` or `.gitignore`.

### source_too_new

The database you are importing from runs a PostgreSQL version newer than any Deplane database can run. Deplane imports from PostgreSQL 9.2 up to the newest version it offers: 18 where Postgres 18 databases are offered, 17 otherwise. The message says which.

Fix: keep the database where it is until Deplane offers its version, or dump and restore it yourself into a server of that version.

From `deplane import heroku`, this means the Heroku database is on a version Deplane does not offer yet (Heroku creates new databases on Postgres 18). The check ends before anything is created on Deplane; see [Moving from Heroku](heroku.md#limits).

### source_too_old

The database you are importing from runs a PostgreSQL version older than 9.2, which Deplane cannot import from.

Fix: upgrade the source database to PostgreSQL 9.2 or later first, or dump and restore it yourself.

### source_unavailable

The uploaded source could not be loaded into the build.

Fix: run `deplane deploy` again. If it keeps happening, email support@deplane.io.

### source_unreachable

Deplane could not connect to the database you are importing from: the host name did not resolve, the connection was refused or timed out, or TLS could not be set up.

Fix: check the host and port in the URL, and allow connections from Deplane's addresses in the database's firewall or its provider's network settings. If the server does not offer TLS, add `?sslmode=disable` to the URL only if you accept an unencrypted connection.

A live import that syncs stops with this code when it could not reach the source for 30 minutes. When a cancelled or failed live import could not reach the source to remove its replication slot and publication, the import still ends, and its page shows the two SQL lines to run on the source: run them, because the slot keeps the source's log from being removed.

### source_wal_held

The live import stopped because its replication slot held more than 5 GiB of your database's log, which the database cannot remove while the slot needs it. The import was stopped, and its slot removed, to protect the source's disk. This happens when the new database falls far behind a busy source.

Fix: start a new import at a quieter time. If it happens again, email support@deplane.io with the import's ID.

### step_up_required

This action needs a fresh confirmation with your second factor from the last 5 minutes (a passkey for admins). Creating tokens, inviting or removing team members, destroying apps, deleting, restoring or switching databases, and admin commands need it. Destroying an app and deleting, restoring or switching a database each use up their confirmation: the next one asks again.

Fix: run the command in a terminal. The CLI opens your browser so you can confirm, then retries. For 5 minutes after that, the other actions also work from scripts. See [Agents, CI, and scripts](agents.md#actions-that-need-a-fresh-passkey).

### subscription_lost

The import's subscription was removed from the new database while the import was syncing, for example by a `DROP SUBSCRIPTION` run there. Without it, changes from your database are no longer copied, so the import stopped. Its replication slot and publication on the source are removed as for a cancelled import.

Fix: start a new import, and do not change the new database until the import is done.

### target_full

The copy needed more room than a Deplane database has, so it was stopped and nothing of it was kept. The limit is 9 GiB, counting the log the copy writes while it runs, so a database can be smaller than that on its own server and still not fit here.

Fix: make the source smaller, for example by deleting old rows or leaving a large schema out, then start a new import. If you need more room, email support@deplane.io.

### team_changed

This dashboard page was opened in another of your teams than the one you work in now: you switched teams in another tab, or you are no longer in that team. Nothing was changed.

Fix: reload the page.

### team_left

You left the team this CLI login was approved for before the CLI collected its token.

Fix: run `deplane login` again and pick a team you are in.

### team_token_required

`DEPLANE_TOKEN` is set, and a token works in one team only, so `--team` cannot pick another.

Fix: drop `--team`, or unset `DEPLANE_TOKEN` to use your stored logins.

### teams_interactive_only

Only your dashboard session or your CLI login can list your teams. A team's CI, agent or AI-tool token cannot see its members' other teams.

Fix: run `deplane teams` after `deplane login`.

### template_app_unhealthy

A template's app was built but did not start (its health check failed). The deploy stopped at its last step; everything it made is kept.

Fix: read the app's logs (`deplane logs --app APP`), then retry with `deplane templates retry DEPLOY-ID` or the dashboard's Retry.

### template_build_failed

A template's build failed. The deploy stopped; everything it made is kept.

Fix: open the build log on the app's page, then retry; a retry builds again.

### template_credentials_not_yours

Only the person who started a template deploy can see the admin sign-in it set up; for a deploy started by a CI token, a team owner can.

Fix: ask the teammate who deployed it, or a team owner.

### template_credentials_shown

The admin sign-in of this template deploy was already shown, more than 10 minutes ago. Deplane shows it once (the same person can ask again within 10 minutes, in case the first answer was lost) and keeps no way to show it later.

Fix: for Vaultwarden, set a new `ADMIN_TOKEN` in the app's Variables and redeploy. Grafana, Listmonk and Gitea offer no reset Deplane can reach: delete the app and deploy the template again, or email support@deplane.io.

### template_deploy_failed

`deplane launch --template` followed a deploy that failed. The message says which step and why.

Fix: run `deplane templates retry DEPLOY-ID` to continue from that step, or `deplane templates delete DEPLOY-ID` to remove what it made.

### template_deploy_not_done

The admin sign-in of a template deploy is shown once the deploy is done.

Fix: wait for the deploy to finish (`deplane templates list` shows it), then ask again.

### template_deploy_not_failed

Only a deploy that failed can be retried; this one is running, done or deleted.

Fix: see where it is with `deplane templates list`.

### template_deploy_running

Your team is already deploying a template (one at a time), or you tried to delete a deploy that is still running.

Fix: wait for it to finish or fail; `deplane templates list` shows it.

### template_needs_upgrade

The template needs more than your plan includes, such as a larger size, more memory, more instances, apps, databases or disk, or an app that never sleeps (on Free, apps sleep when idle, which would stop the background work of templates such as Listmonk or Miniflux). The message says what it needs and what your plan has.

Fix: see the larger plans at https://deplane.io/pricing, or email support@deplane.io.

### template_no_credentials

This deploy's template sets up no admin sign-in, or the deploy was made before its template did (2026-10-27), so there is nothing to show.

Fix: follow the template's note to sign in.

### template_no_room

Your plan could hold the template, but your team is using too much of it right now. The message says what it needs and what is free.

Fix: destroy or scale down an app (`deplane apps`), or delete a database or disk you no longer need, then deploy again.

### template_not_found

There is no template with that name.

Fix: see the templates with `deplane templates list` or at https://deplane.io/templates.

### template_not_ready

This template's image is not ready yet, so it cannot be deployed.

Fix: pick another template, or try again later.

### template_resource_gone

Something a template deploy made (its app, database or disk) was deleted outside the deploy, so it cannot continue.

Fix: delete the deploy (Delete all of it, or `deplane templates delete DEPLOY-ID`) and deploy the template again.

### template_timeout

A step waited too long: the database was not ready in 15 minutes, or the build and rollout took more than 45.

Fix: retry. If it keeps happening, email support@deplane.io.

### temporarily_unavailable

Sign-ups are paused for now. Every address gets this answer, whether or not it already has an account; when sign-ups are open, every address gets an email with a sign-in link instead.

Fix: try again later, or write to the support address shown with the error.

### token_in_env

`DEPLANE_TOKEN` is set, so a stored login would not be used.

Fix: unset `DEPLANE_TOKEN`, then run `deplane login` again.

### too_many_alert_channels

A team can have 10 alert channels.

Fix: Remove one you no longer use first.

### too_many_databases

The old code for a team with as many databases as it may have. Deplane now answers [limit_databases](#limit_databases), with your plan's number.

Fix: see [limit_databases](#limit_databases).

### too_many_deploys

The app was deployed 10 times in the last hour, the most allowed per app.

Fix: wait a few minutes and deploy again. Commands that do not build, such as `deplane scale`, `deplane secrets set`, and `deplane rollback`, still work.

### too_many_domains

The app already has 10 custom domains, the most allowed.

Fix: remove a domain you no longer use, then add the new one.

### too_many_import_checks

Your team has started 20 import checks in the last 24 hours, the most Deplane allows.

Fix: try again later: the limit counts the 24 hours before each check. If you need more, email support@deplane.io.

Redis imports have their own 20 a day per team.

### too_many_invites

The team has 20 open invitations, the most allowed.

Fix: revoke invitations that were not used.

### too_many_log_reads

Your team is already reading kept logs twice at once.

Fix: wait for one to finish, then try again.

### too_many_processes

The app already has 10 workers and cron jobs, the most allowed.

Fix: remove one you no longer need first.

### too_many_uploads

Your organization already has two uploads in progress.

Fix: wait for them to finish, then run the command again.

### totp_exists

An authenticator app is already set up on this account.

Fix: use your existing authenticator app.

### totp_setup_missing

No authenticator setup is in progress.

Fix: open the authenticator setup page again.

### totp_unavailable

Authenticator apps are not available for this account. Admin accounts use only passkeys.

Fix: use a passkey or security key.

### unauthorized

Your login is missing, expired, or revoked.

Fix: run `deplane login`. In CI, check that `DEPLANE_TOKEN` holds a token that has not expired or been revoked.

### unexpected_argument

The command got an argument it does not take.

Fix: run `deplane help` for usage. See the [CLI reference](cli.md).

### unknown_command

There is no such command.

Fix: run `deplane help` to see the commands.

### unknown_file

A detection request included a file that detection does not read.

Fix: send only the project's manifest files (package.json, requirements.txt, pyproject.toml, go.mod, Gemfile, composer.json, pom.xml, Dockerfile, index.html, and similar). The dashboard does this for you.

### unknown_flag

There is no such flag.

Fix: run `deplane help` to see the flags.

### unknown_setting

That setting cannot be changed from the admin console.

Fix: Use one of the settings listed in Admin, Settings.

### unsafe_link

A symbolic link in the project points outside the project folder.

Fix: remove the link, or copy what it points to into the project folder. `deplane deploy` skips such links and tells you.

### unsafe_path

The upload contains a path that is unsafe: outside the project folder, through a symbolic link, or listed twice.

Fix: upload with `deplane deploy`, which packages each file once and only from the project folder. Replace symbolic links to folders with real folders.

### unsupported_entry

The upload contains something that is not a file, folder, or symbolic link.

Fix: remove device files, pipes, and hard links from the project folder.

### unsupported_grant_type

The token request used a grant type Deplane does not offer.

Fix: use `authorization_code` or `refresh_token`.

### unsupported_media_type

A deploy was sent neither as a gzip-compressed tar archive nor as JSON naming an image.

Fix: use `deplane deploy`, which packages and uploads the folder for you, or `deplane deploy --image REF` for a public image.

### unsupported_response_type

Deplane supports only the authorization code flow (`response_type=code`).

Fix: update the AI tool and connect again. If you build the tool, use the authorization code flow with PKCE.

### upload_interrupted

The upload was interrupted.

Fix: run the command again. The CLI retries uploads automatically.

### url_in_argument

You typed something after `deplane db import`. The CLI never takes the source database's URL as an argument: it would land in your shell history and in the process list, with its password.

Fix: run `deplane db import` and paste the URL when asked, or pipe it in from a variable or a file.

`deplane redis import` refuses any argument the same way, without repeating it: the Redis URL and a file link carry a password. Fix: run `deplane redis import` (with `--rdb-url` for a link) and paste it when asked, or pipe it in; for a file on this computer, use `--rdb FILE`.

### usage

The build runner was started incorrectly. This is a problem on our side.

Fix: run `deplane deploy` again. If it keeps happening, email support@deplane.io.

### verify_failed

After the copy, Deplane counted the rows of every table in the new database, and the counts did not match the source's at the moment the copy was taken. The message names up to five tables with both counts. Nothing of the copy was kept: the new database is empty again.

Fix: start a new import. If it happens again, email support@deplane.io with the import's ID.

### invalid_redis_name

A Redis name is 3 to 30 characters: lowercase letters, digits and single hyphens, starting with a letter.

Fix: pick a name such as `cache`, `queue` or `sessions`.

### limit_redis

Your plan allows fewer Redis than your team would then have.

Fix: destroy one you no longer need with `deplane redis destroy NAME`, or email support@deplane.io to raise the limit.

### mcp_redis_url

AI tools connected to Deplane cannot set `REDIS_URL` by hand.

Fix: attach a Redis with the `attach_redis` tool, or set it yourself in the dashboard. See [MCP](mcp.md).

### no_redis_space

There is no free Redis space on the platform right now. We are alerted automatically.

Fix: try again later, or email support@deplane.io.

### redis_attached_elsewhere

The app already uses another Redis as `REDIS_URL`. An app has one Redis.

Fix: detach the other one first with `deplane redis detach NAME --app APP`.

### redis_exists

Your team already has a Redis with that name.

Fix: pick another name.

### redis_failed

The Redis a template deploy made could not start.

Fix: Retry; if it fails again, email support@deplane.io.

### redis_not_found

Your team has no Redis with that name.

Fix: see your team's Redis with `deplane redis list`.

### redis_on_preview

A pull request preview cannot use a Redis.

Fix: attach the Redis to the app itself; its previews run without it.

### redis_url_in_use

The app already has a variable called `REDIS_URL` that did not come from a Redis here, and attaching would overwrite it.

Fix: remove it with `deplane secrets unset REDIS_URL --app APP`, then attach the Redis.

### redis_busy

Apps kept attaching to the Redis while it was being destroyed, so it was left as it was.

Fix: try destroying it again.

### redis_importing

An [import](redis-import.md) is still filling this Redis, so it cannot be attached, destroyed, backed up or restored yet.

Fix: wait until the import is done (`deplane redis import status`), or cancel it with `deplane redis import cancel`.

### redis_import_active

Your team already has a Redis import in progress. A team has one at a time, from the check until it is done, cancelled, failed or expired. A Postgres import does not count.

Fix: wait for it to finish, or cancel it with `deplane redis import cancel`, then start the new one.

### redis_import_not_found

Your team has no Redis import with that ID.

Fix: see your team's newest Redis import with `deplane redis import status`.

### invalid_import_id

`deplane redis import status` or `cancel` was given something that is not a Redis import ID (they start with `rdi_`). The CLI does not repeat it, in case it was a URL or a password.

Fix: pass one import ID, or none for the newest import. `deplane redis import status` shows it with its ID.

### invalid_import_source

A Redis import needs exactly one source: the Redis's URL, or a link to an RDB file. The request had both, or neither. A Postgres import also takes one source: a database URL (`source_url`) or one of your team's databases (`source_database`), and the request had both.

Fix: for a running Redis, give its `redis://` or `rediss://` URL; for a saved file, an `https://` link to it, or upload it with `deplane redis import --rdb FILE`. For Postgres, give only the URL, or only the name of the database to copy.

### invalid_rdb_link

The link to the RDB file cannot be used. It must be an `https://` link to one host, with no user name or password in it, at most 4096 characters, and the file must be reachable on the internet. A link whose redirect is not `https`, or that redirects more than 3 times, is refused too. Deplane never repeats the link in an error.

Fix: paste a direct download link, such as a presigned S3 link (`aws s3 presign s3://BUCKET/FILE.rdb --expires-in 3600`). For a running Redis, run `deplane redis import` without `--rdb-url` and paste its URL.

### link_failed

Deplane could not download the RDB file from the link: the host did not answer, refused the download (an expired presigned link answers HTTP 403), or ended it early.

Fix: make a new link that does not expire for an hour, check that it downloads the file in a browser, and import again.

### fetch_failed

Downloading the RDB file from the link failed inside the importer.

Fix: import again. If it keeps happening, email support@deplane.io with the import's ID.

### rdb_file_unreadable

`deplane redis import --rdb FILE` could not read the file: it does not exist, is a folder, or you may not read it. The CLI does not repeat what you gave, in case it was a link.

Fix: pass the path of the `dump.rdb` file on this computer. For a link, use `deplane redis import --rdb-url` and paste it when asked.

### not_rdb

The file is not an RDB file: it does not start with `REDIS` and a 4-digit version. A link may have downloaded a web page instead of the file.

Fix: give the `dump.rdb` file Redis wrote (with `SAVE` or `BGSAVE`, in the folder `CONFIG GET dir` names), or a link that downloads that file directly.

### rdb_too_new

The file was made by a Redis newer than a Deplane Redis can load: RDB version 12 or later (Redis 7.4 and 8, Valkey 9). A Deplane Redis (Valkey 8) loads version 11 or older.

Fix: copy that Redis from its URL instead with `deplane redis import`: a newer Redis is copied type by type. See [Import a Redis](redis-import.md#from-the-url).

### file_too_large

The RDB file is larger than 256 MB, the most Deplane loads.

Fix: copy the Redis from its URL instead (`deplane redis import`): only its data has to fit, up to 150 MB. A file holds more than the data in memory, and a Redis whose data is bigger does not fit a Deplane Redis either way.

### length_required

The upload did not say how long the file is (no `Content-Length`).

Fix: upload with `deplane redis import --rdb FILE` or from the dashboard, which both send it. From your own script, send the file with its length, not in chunks.

### upload_incomplete

The upload of the RDB file ended before its length: the connection broke, or the file changed while it was sent.

Fix: upload it again. The import that was started for it ends; the Redis it created stays, empty, so pick another name or delete it with `deplane redis destroy NAME` first.

### upload_failed

The importer could not send the downloaded file to Deplane's backup store. This is a problem on our side; the import tries again by itself before it fails.

Fix: import again. If it keeps happening, email support@deplane.io with the import's ID.

### upload_refused

Deplane's backup store refused the file: the import's one-time upload key was already used or had expired.

Fix: import again. If it happens again, email support@deplane.io with the import's ID.

### import_unavailable

The check found that this Redis or file cannot be imported, so it cannot be started. The message gives the reason, for example that the data is bigger than 150 MB, that the Redis runs in cluster mode, or that it holds keys of module types.

Fix: fix what the message names on the source, then run `deplane redis import` again. See [Import a Redis](redis-import.md#limits).

### source_db_unavailable

The source Redis refused to select the database the URL names (the number after the last `/`).

Fix: check the number in the URL. Most hosts have only database 0: leave the number out, or use `/0`.

### source_lost

The connection to the source Redis broke during the check or the copy. A copy tries again by itself before it fails.

Fix: check that the source is up and still lets Deplane connect, then import again.

### target_unreachable

The importer could not connect to the new Redis. This is a problem on our side; the copy tries again by itself before it fails.

Fix: import again. If it keeps happening, email support@deplane.io with the import's ID.

### target_lost

The connection to the new Redis broke during the copy, or it stopped answering. The copy tries again by itself, starting over, before it fails.

Fix: import again. If it keeps happening, email support@deplane.io with the import's ID.

### interrupted

The copy was stopped before it finished, for example because a server restarted. It starts over by itself, from an emptied Redis, before the import fails.

Fix: if the import failed, import again.

### timeout

The copy took longer than 30 minutes, the most a Redis import may take. A Redis that fits copies in a minute or two, so the source was probably very slow or far away.

Fix: import again when the source is less busy, or load an RDB file instead (`deplane redis import --rdb FILE`).

### too_big

The data needs more room than a Deplane Redis has: it holds 200 MB of data, and the copy or the load stopped at 190 MB.

Fix: delete keys you do not need from the source (old cache entries, for example), then import again. The new Redis stays, empty: delete it with `deplane redis destroy NAME` first, or import under another name.

### unsupported_type

A key has a type a Deplane Redis does not have: a module type such as RedisJSON, RediSearch, Bloom filters or TimeSeries. The message names the key. Nothing was skipped: the import stops instead.

Fix: delete or convert those keys on the source (store JSON as a string, for example), then import again.

### value_too_large

A key holds more than 64 MB, the most Deplane copies for one key. The message names the key.

Fix: split or delete that key on the source, then import again.

### invalid_mysql_name

A MySQL name is 3 to 30 characters: lowercase letters, digits and single hyphens, starting with a letter.

Fix: pick a name such as `shop`, `blog` or `orders`.

### invalid_mysql_size

A MySQL is medium (1 GB of memory) or large (2 GB). There is no small MySQL.

Fix: leave the size out for medium, or pick `large`.

### limit_mysql

Your plan allows fewer MySQL than your team would then have.

Fix: destroy one you no longer need with `deplane mysql destroy NAME`, or email support@deplane.io to raise the limit.

### mysql_attached_elsewhere

The app already uses another MySQL as `MYSQL_URL`. An app has one MySQL.

Fix: detach the other one first with `deplane mysql detach NAME --app APP`.

### mysql_busy

Apps kept attaching to the MySQL while it was being destroyed, so it was left as it was.

Fix: try destroying it again.

### mysql_exists

Your team already has a MySQL with that name.

Fix: pick another name.

### mysql_failed

The MySQL a template deploy made could not start.

Fix: Retry; if it fails again, email support@deplane.io.

### mcp_mysql_url

AI tools connected to Deplane cannot set `MYSQL_URL` by hand.

Fix: attach a MySQL with the `attach_mysql` tool, or set it yourself in the dashboard. See [MCP](mcp.md).

### mysql_not_found

Your team has no MySQL with that name.

Fix: see your team's MySQL with `deplane mysql list`.

### mysql_on_preview

A pull request preview cannot use a MySQL.

Fix: attach the MySQL to the app itself; its previews run without it.

### mysql_url_in_use

The app already has a variable called `MYSQL_URL` that did not come from a MySQL here, and attaching would overwrite it.

Fix: remove it with `deplane secrets unset MYSQL_URL --app APP`, then attach the MySQL.

### invalid_clickhouse_name

A ClickHouse database name is 3 to 30 characters: lowercase letters, digits and single hyphens, starting with a letter.

Fix: pick a name such as `events`, `analytics` or `stats`.

### invalid_clickhouse_size

A ClickHouse database is large (2 GB of memory). There is no small or medium size.

Fix: leave the size out, or pick `large`.

### limit_clickhouse

Your plan allows fewer ClickHouse databases than your team would then have.

Fix: destroy one you no longer need with `deplane clickhouse destroy NAME`, or email support@deplane.io to raise the limit. See [ClickHouse](clickhouse.md#limits).

### clickhouse_attached_elsewhere

The app already uses another ClickHouse database as `CLICKHOUSE_URL`. An app has one ClickHouse database.

Fix: detach the other one first with `deplane clickhouse detach NAME --app APP`.

### clickhouse_busy

Apps kept attaching to the ClickHouse database while it was being destroyed, or attaching and detaching while a restore was starting, so it was left as it was.

Fix: try again.

### clickhouse_exists

Your team already has a ClickHouse database with that name.

Fix: pick another name.

### clickhouse_failed

The ClickHouse database a template deploy made could not start.

Fix: Retry; if it fails again, email support@deplane.io.

### clickhouse_not_found

Your team has no ClickHouse database with that name.

Fix: see your team's ClickHouse databases with `deplane clickhouse list`.

### clickhouse_on_preview

A pull request preview cannot use a ClickHouse database.

Fix: attach the ClickHouse database to the app itself; its previews run without it.

### clickhouse_url_in_use

The app already has a variable called `CLICKHOUSE_URL` that did not come from a ClickHouse database here, and attaching would overwrite it.

Fix: remove it with `deplane secrets unset CLICKHOUSE_URL --app APP`, then attach the ClickHouse database.

### mcp_clickhouse_url

AI tools connected to Deplane cannot set `CLICKHOUSE_URL` by hand.

Fix: attach a ClickHouse database with the `attach_clickhouse` tool, or set it yourself in the dashboard. See [MCP](mcp.md).

### restore_no_room

The ClickHouse backup holds more than about 4.5 GB. A restore needs room for the downloaded backup and the data loaded from it on the same 10 GB disk, so there is no room to restore it. Nothing was stopped or changed.

Fix: contact support to restore it. Keep the data under about 4.5 GB so that every backup can be restored. See [The 45% rule](clickhouse.md#the-45-rule).

### watch_not_allowed

A watch token tried something other than reading the platform's health or reporting checks and drills.

Fix: use your own login for anything else.

### missing_heroku_app

`deplane import heroku` needs the name of the Heroku app to import.

Fix: run `deplane import heroku my-app --check`; `heroku apps` lists your apps. See [Moving from Heroku](heroku.md).

### invalid_heroku_app

The argument to `deplane import heroku` is not a Heroku app name. It is not repeated in the message, in case it was a token.

Fix: pass the app's name: lowercase letters, digits and dashes, as `heroku apps` shows it.

### token_in_argument

A provider token was typed on the command line of a `deplane import` command (`heroku`, `render`, `railway`, `fly`, `vercel` or `netlify`: as the argument, or as the value of `--name` or `--source`), a cPanel API token on the command line of `deplane import cpanel` (as an argument or a flag's value), or a Cloudflare token on the command line of `deplane domains switch`. The CLI never takes a token as an argument: it would land in your shell history and the process list. The token is not repeated in the message. For cPanel, pipe it in or set `CPANEL_API_TOKEN`, then revoke the one you typed (cPanel, Security, Manage API Tokens).

Fix: pipe it in, paste it at the hidden prompt, or set the provider's variable (`HEROKU_API_KEY`, `RENDER_API_KEY`, `RAILWAY_TOKEN`, `FLY_API_TOKEN`, `VERCEL_TOKEN`, `NETLIFY_AUTH_TOKEN`, `CLOUDFLARE_API_TOKEN`). For Heroku: `heroku authorizations:create --scope read-protected --expires-in 3600 --short | deplane import heroku APP`. Then revoke the token you typed (for Heroku, `heroku authorizations:revoke ID`; for Fly.io, `fly tokens revoke ID`; for the others, delete it in their dashboard), since your shell history now holds it.

### heroku_token_missing

`deplane import heroku` got no Heroku token: nothing was piped in, nothing was typed at the prompt, and `HEROKU_API_KEY` is not set. In the dashboard's **Import from another platform**, the same code means the token field was empty.

Fix: pipe one in: `heroku authorizations:create --scope read-protected --expires-in 3600 --short | deplane import heroku APP`, or set `HEROKU_API_KEY`. There is no flag for the token.

### heroku_token_unreadable

What was piped into `deplane import heroku` is not one token: it has spaces or several lines, or is too long. This is usually the table `heroku authorizations:create` prints without `--short`. In the dashboard, it means what was pasted is not one token (several lines, spaces, or too long).

Fix: add `--short`, so that only the token is piped in.

### heroku_token_invalid

Heroku refused the token (HTTP 401): it is mistyped, expired or revoked. A token from `--expires-in 3600` lasts an hour. In the dashboard, the same code means the pasted token was refused; it is never shown back.

Fix: create a new one with `heroku authorizations:create --scope read-protected --expires-in 3600 --short` and run the command again.

### heroku_forbidden

Heroku did not let the token read the app (HTTP 403). The token's account has no access to it, or, for a team app, a team admin turned off third-party access.

Fix: create the token while logged in to the Heroku CLI as an account with access to the app, or ask a team admin.

### heroku_config_vars_forbidden

This token can't read config vars: create it with `--scope read-protected`. A `read` or `identity` token can read the app but not its config vars, and the import needs them, `DATABASE_URL` included.

Fix: run `heroku authorizations:create --scope read-protected --expires-in 3600 --short` and pipe that token in. It can only read; it cannot change anything on Heroku.

### heroku_app_not_found

Heroku has no app with that name that the token can see.

Fix: check the name with `heroku apps`, and that the token belongs to an account with access to the app.

### heroku_rate_limited

Heroku's API limit for your account is used up for now (HTTP 429). Heroku allows 4500 calls an hour per account; an import makes about 10.

Fix: wait a few minutes and run the command again.

### heroku_unreachable

The CLI could not reach Heroku's API (`api.heroku.com`), or the answer was cut off.

Fix: check your internet connection and run the command again.

### heroku_error

Heroku's API answered with an error the CLI does not expect, for example HTTP 500. The message names the request.

Fix: run the command again in a few minutes, and check https://status.heroku.com.

### heroku_bad_response

Heroku sent an answer the CLI cannot read.

Fix: update the CLI and run the command again. If it keeps happening, email support@deplane.io with the message.

### heroku_import_refused

The report of `deplane import heroku` has a ✗ line: something stops the import, for example a folder with no files, a database in a Heroku Private Space or Shield space, a folder that belongs to another Deplane app, or a plan limit the import would cross (workers on a plan whose apps sleep, a size the plan lacks, or more apps, databases, Redis, instances or memory than it allows). Nothing was created on Deplane.

Fix: do what the ✗ lines say, then run the command again. For a plan limit, free room or email support@deplane.io to change your plan. See [Moving from Heroku](heroku.md#plan-limits).

### compose_import_refused

The report of `deplane import compose` (or the dashboard's **Import from Docker Compose**) has a ✗ line: something in the file cannot move as it is, for example a privileged service, a host network, a host folder mounted by absolute path, a port below 1024, two databases of one kind, a service built from a folder in the dashboard, or a plan limit the import would cross. Nothing was created on Deplane.

Fix: do what the ✗ lines say, then import again. See [Moving from Docker Compose](compose.md#what-cannot-move).

### compose_file_not_found

`deplane import compose` found no `compose.yaml`, `compose.yml`, `docker-compose.yaml` or `docker-compose.yml` in the current folder, or the file given with `-f` does not exist.

Fix: run the command in the folder with your compose file, or pass it with `-f FILE`.

### compose_invalid

The compose file is not valid YAML, has no services, holds more than one document, or has a field in a form Deplane cannot read.

Fix: check it with `docker compose config`, fix what it says, and import again.

### compose_too_large

The compose file is larger than 256 KB, or has more than 64 services.

Fix: import the services you move, in a smaller file.

### compose_too_complex

The compose file nests deeper than 32 levels, uses anchors and aliases more than 200 times, has more than 20000 values or 512 KB of text once its aliases are expanded, or its variables would take too long to plan (more than 5 seconds in the dashboard). A file built to grow when it is read (a "YAML bomb") is refused this way, before it costs anything.

Fix: remove deep nesting or repeated aliases, or run `docker compose config > resolved.yml` and import `resolved.yml`.

### compose_unsupported

The compose file includes other files (`include:`), which the import does not read.

Fix: run `docker compose config > resolved.yml` and import `resolved.yml`: it is your file with every include, extends and variable worked out.

### compose_variable_required

The compose file uses `${VAR:?message}` or `${VAR?message}`, and the variable is not set. The dashboard has no environment, so it never has one.

Fix: set it in your environment or in `.env` beside the file and run `deplane import compose`.

### compose_import_interactive_only

A CI token or an AI tool asked the API to check or import a compose file. Both are for a person at their own login (a `deplane login` or a dashboard session): `deplane import compose` plans on your own computer, and a compose file usually carries passwords.

Fix: import from the dashboard, or with `deplane import compose` after `deplane login`.

### repo_invalid

What you gave is not a GitHub repository Deplane can read: the forms are `owner/repo`, `github.com/owner/repo` and `https://github.com/owner/repo`, each optionally followed by `@BRANCH`, `@TAG` or `@COMMIT`. Only github.com is supported.

Fix: give the repository in one of those forms.

### repo_not_found

The repository was not found, or it is not public. Deplane fetches public GitHub repositories without any token, so a private repository looks the same as a missing one; a renamed repository is not followed to its new name.

Fix: check the name; make the repository public, or deploy it as your own code with `deplane launch` from a clone.

### repo_ref_not_found

The repository has no branch, tag or commit with the name you gave after `@`.

Fix: check the name, or leave it out for the default branch.

### repo_template_missing

The repository has no `deplane.template.json` at its root at that commit.

Fix: add the file (see [Templates](templates.md#deploy-from-your-own-repository)), or deploy the repository as your own code with `deplane launch`.

### repo_template_invalid

The repository's `deplane.template.json` breaks one or more rules; the message lists them (an unknown field, a missing `title` or `app.port`, a credential written as a literal, a reference to an engine the file does not ask for, ...).

Fix: fix the file in the repository, then check again. Nothing was created.

### repo_too_large

The `deplane.template.json` is larger than 64 KB, or the repository's source is larger than Deplane reads: more than 100 MB as GitHub sends it, or more than the upload limits once unpacked.

Fix: keep the file small, and build output, dependencies and large data files out of the repository.

### repo_changed

The repository moved between your check and your deploy: the branch or tag now points at another commit, so what would be deployed is not what you read. Nothing was created.

Fix: check it again, read what it asks for now, then deploy.

### repo_unreachable

GitHub did not answer as expected when Deplane read the repository.

Fix: try again in a minute. If it keeps failing, check GitHub's status.

### repo_source_failed

At the build step, GitHub's download of the commit could not be read as a complete archive, or it was larger than the upload limits allow. The deploy failed at that step; what was made before it is kept.

Fix: Retry downloads it again. Keep build output, dependencies and large data files out of the repository.

### repo_source_empty

At the build step, the repository had no files at that commit.

Fix: push the code, then deploy again.

### repo_deploys_unavailable

Deploying from a repository is not set up on this platform.

Fix: deploy the repository as your own code with `deplane launch` from a clone.

### flag_conflict

`--repo` was given together with `--template`, `--image` or `--port`, which name another thing to deploy.

Fix: run `deplane launch --repo OWNER/REPO [--name APP]` on its own.

### repo_deploy_interactive_only

A CI token or an AI tool asked the API to check or deploy a repository. Both are for a person at their own login (a `deplane login` or a dashboard session): an AI tool deploying code from an arbitrary repository into your team is not something Deplane allows.

Fix: deploy from the dashboard (New app, Deploy from a GitHub repository), or with `deplane launch --repo` after `deplane login`.

### too_many_repo_checks

Your team checked or deployed 30 repositories in the last 10 minutes, the most allowed (each check reads GitHub).

Fix: wait a few minutes and try again.

### invalid_prefix

`--prefix` (or the dashboard's App name for an import) is not an app name of at most 30 characters.

Fix: use lowercase letters, digits and single hyphens, starting with a letter, such as `--prefix shop`.

### invalid_refs

`PUT /v1/apps/APP/secrets` was sent `refs` that Deplane cannot fill in: a reference that is not a known field of an attached Postgres, Redis, MySQL or ClickHouse database, a value that is not only references, `refs` for build-time secrets, a variable in both `values` and `refs`, or `DATABASE_URL`, `REDIS_URL`, `MYSQL_URL` or `CLICKHOUSE_URL`, which attaching sets.

Fix: use references such as `${postgres.host}`, `${postgres.password}` or `${mysql.host}:${mysql.port}`, one per variable, for runtime secrets. See the [OpenAPI description](https://api.deplane.io/v1/openapi.yaml).

### too_many_compose_checks

Your team checked or imported 30 compose files in the dashboard (or through the API) in the last 10 minutes.

Fix: wait a few minutes and try again. `deplane import compose --check` plans on your own computer and has no such limit.

### mcp_refs

An AI tool sent `refs` to fill a variable in from an attached database. AI tools change an app's database only by attaching it.

Fix: attach the database with the AI tool's attach tool, or set the references yourself with the CLI or the dashboard.

### attachment_missing

`refs` named a database, Redis, MySQL or ClickHouse database that is not attached to the app, so its connection details cannot be filled in.

Fix: attach it first (`deplane db attach NAME --app APP`, or the `redis`, `mysql` or `clickhouse` attach command), then set the references again.

### engine_failed

A database, Redis, MySQL or ClickHouse database that `deplane import compose` created could not be made ready.

Fix: destroy it and create it again by hand with the commands the import printed. If it keeps failing, email support@deplane.io.

### engine_timeout

A database, Redis, MySQL or ClickHouse database that `deplane import compose` created was not ready after 15 minutes.

Fix: check it with `deplane db`, `deplane redis list`, `deplane mysql list` or `deplane clickhouse list`, then run the remaining steps the import printed.

### import_provider_unknown

The dashboard's **Import from another platform** was asked for a platform it does not import from here: not one of Heroku, Render, Railway, Fly.io, Vercel and Netlify, or one that is not switched on for this Deplane installation yet (each goes live after a check with a real account). Its API routes do not exist (HTTP 404).

Fix: the Import page lists the platforms you can pick. From your own machine, `deplane import` has one more, Docker Compose.

### import_dashboard_only

An import with a pasted token is the dashboard's: a CLI token cannot call it. The CLI never needs to, because `deplane import heroku`, `render`, `railway`, `fly`, `vercel` and `netlify` read the platform on your own machine, and the token never leaves it.

Fix: run `deplane import PROVIDER NAME` from your machine, or use **Import from another platform** in the dashboard. CLI and CI tokens cannot list or read the dashboard's imports either.

### import_refused

The report of the dashboard's **Import from another platform** has a ✗ line: something stops the import, for example a database Deplane cannot copy (a Heroku Private Space, a Render allow list that keeps Deplane out, a Railway Postgres without a public address), a name another team already uses, or a plan limit the import would cross (workers on a plan whose apps sleep, a size the plan lacks, or more apps, databases, Redis, instances or memory than it allows). The same lines are on the report; Import refuses with this code until they are gone. Nothing was created on Deplane.

Fix: do what the ✗ lines say, then check again. For a name another team holds, pick another name. For a plan limit, free room or email support@deplane.io to change your plan. See [Plan limits](heroku.md#plan-limits). The CLI's own codes are `heroku_import_refused`, `render_import_refused`, `railway_import_refused`, `fly_import_refused`, `vercel_import_refused` and `netlify_import_refused`.

### import_running

Your team is already importing an app from another platform in the dashboard. A team runs one at a time; an import that waits for secrets does not count.

Fix: wait until that import is done or has failed (the Import page shows it), then start the next.

### import_not_allowed

A dashboard import acts for the person who started it, and that person is no longer an active member of the team (removed, or their account or the team suspended), so it stopped before its next step. What it created so far stays, listed on its page.

Fix: a member can delete what it created (**Delete what it created** on the import's page), or import again.

### import_name_taken

While a dashboard import waited (for example for the database check), an app or a Redis with the name it planned appeared that the import did not create. The import stopped rather than use it: it never takes over something else.

Fix: delete what the import created so far, and import again with another app name.

### import_not_yours

Only the person who started a dashboard import, or a team owner, can cancel it, deploy it after setting its secrets, or delete what it created.

Fix: ask them to.

### import_not_running

The dashboard import already ended (done, failed or cancelled), so there is nothing to cancel.

Fix: reload the page to see how it ended.

### import_not_waiting

**Deploy** was pressed on a dashboard import that is not waiting for secrets: it is still running, already deploying, or ended.

Fix: reload the page to see where it is.

### import_waiting_for_secrets

A dashboard import from Fly.io, Vercel or Netlify stopped at **Set secrets**, because those platforms never give back the values of their secrets (Fly.io secrets, Vercel and Netlify secret variables), and **Deploy** was pressed while the app still lacks some of the names the report listed. The message names them. The import stays waiting; nothing times it out.

Fix: set them in the form (the platform's values, which you take from where you keep them, never from the import), then press Deploy. Deploy without them only if the app does not need them any more.

### import_undo_not_allowed

**Delete what it created** works only for a failed or cancelled import. A done import is your app now, and a running or waiting one is still at work.

Fix: cancel the import first, or delete the app, database or Redis from their own pages.

### import_timeout

A step of a dashboard import waited longer than it may: 20 minutes for the database check, 6 hours for the database copy, 15 minutes for the Redis, 45 minutes for the build and deploy. The wait for secrets never times out. The import stopped there; what it created so far stays and is listed on its page.

Fix: delete what it created and import again. If it keeps happening, email support@deplane.io with the import's ID.

### import_resource_gone

Something a dashboard import had created (its app, database or Redis) was deleted while the import was still running, so it stopped.

Fix: delete what is left of it and import again.

### import_build_failed

The dashboard import connected the GitHub repository and built it, or pulled the image the platform runs, and the build failed. The app, its secrets, database and Redis are in place.

Fix: read the build log on the app's page. For a repository, fix the code and push: every push to the connected branch deploys. For an image, check that it is public and runs on Deplane, then press Rebuild there.

### import_app_unhealthy

The imported app was built, but it did not start or did not pass its health check. The message says why.

Fix: read the app's logs on its page. A Deplane app must listen on 0.0.0.0 at `$PORT`; check that the start command matches what the platform ran (the report shows it). Then push a fix.

### missing_repository

A dashboard import deploys a GitHub repository, and none was picked, or the platform builds one you have not given Deplane access to (the message names it). The repository is matched only among the ones you granted: a name read from the platform never widens what Deplane can read.

Fix: press **Connect GitHub**, choose that repository in the Deplane app's settings on GitHub, and pick it; or pick another repository that holds the app's code. Where the platform runs an image (Fly.io Machines, a Render or Railway image service), switch the source to the image instead.

### missing_image

The source was set to the image, but the platform runs this app from code, not from an image, so there is no image to deploy.

Fix: pick the repository that holds the app's code.

### import_image_invalid

The image the platform runs, or the one typed in its place, is not an image reference Deplane can deploy.

Fix: use a public reference such as `ghcr.io/owner/app:1.2` (a tag or a digest), or pick a repository instead.

### import_image_private

The image the platform runs is in a private registry, which Deplane cannot pull from. The check shows it as a ⚠ line and preselects a repository; the import refuses with this code.

Fix: pick a repository instead, or push the image to a public registry and import it from there.

### image_imports_unavailable

The import would deploy the image the platform runs, and this Deplane installation cannot deploy images here yet.

Fix: pick a repository instead.

### import_invalid_schedule

A cron job the import would create has a schedule Deplane does not accept (the message names the job). Nothing was created.

Fix: change the schedule on the platform and import again, or import without it and add the job afterwards with `deplane processes add --schedule`.

### invalid_commit

The commit to deploy is not a full git commit ID.

Fix: give all 40 characters of the commit, or leave it out to deploy the commit the platform runs.

### commit_not_found

The commit to deploy is not in the GitHub repository you picked, or the Deplane GitHub App cannot read it.

Fix: push the commit to the repository, or leave the commit out: the import then deploys the commit the platform runs when the repository has it, else the newest commit of the branch.

### source_not_found

The folder to deploy (`--source`, or the current folder) does not exist or cannot be read.

Fix: pass the folder with the app's code with `--source DIR`, for example a clone of the repository you deploy to Heroku.

### source_empty

The folder to deploy has no files (a `.git` folder alone does not count).

Fix: run the command in a checkout of the app's code, or pass it with `--source DIR`. Check out the commit Heroku runs: the report shows it.

### source_other_app

The folder to deploy has a `deplane.toml` that names another Deplane app. Deploying it would point that file at the imported app.

Fix: import from a folder without `deplane.toml` (a fresh checkout, with `--source DIR`), or remove the file from this one.

### missing_render_service

`deplane import render` needs the Render service to import.

Fix: pass its ID (`srv-...`, in the service's address in the Render Dashboard) or its name: `deplane import render my-web --check`. See [Moving from Render](render.md).

### invalid_render_service

The argument to `deplane import render` is not a Render service ID or name. It is not repeated in the message, in case it was a key.

Fix: pass the web service's ID (`srv-...`) or its name as the Render Dashboard shows it.

### render_token_missing

`deplane import render` got no Render API key: nothing was piped in or typed at the prompt, and `RENDER_API_KEY` is not set. In the dashboard's **Import from another platform**, the same code means the token field was empty.

Fix: create a key in the Render Dashboard (Account Settings → API Keys), then paste it at the hidden prompt, pipe it in, or set `RENDER_API_KEY`. There is no flag for it.

### render_token_unreadable

What was piped into `deplane import render` is not one API key: it has spaces or several lines, or is too long. In the dashboard, it means what was pasted is not one token (several lines, spaces, or too long).

Fix: pipe in only the key, on one line.

### render_token_invalid

Render refused the API key (HTTP 401): it is mistyped, or was deleted. In the dashboard, the same code means the pasted token was refused; it is never shown back.

Fix: create a new key in the Render Dashboard (Account Settings → API Keys) and run the command again.

### render_forbidden

Render did not let the key read part of the service (HTTP 403): its account is not a member of the service's workspace, or lacks access.

Fix: use a key of an account that is a member of the workspace.

### render_service_not_found

Render has no service with that ID or name that the key can see.

Fix: check the ID or name in the Render Dashboard, and that the key's account is in the service's workspace.

### render_service_ambiguous

Several services the key can see have that name (in different workspaces or environments). The message lists their IDs and types.

Fix: pass the ID of the one to import: `deplane import render srv-... --check`.

### render_rate_limited

Render's API limit for your account is used up for now (HTTP 429).

Fix: wait a minute and run the command again. An import makes about 15 calls to Render.

### render_unreachable

The CLI could not reach Render's API (`api.render.com`), or the answer was cut off.

Fix: check your internet connection and run the command again.

### render_error

Render's API answered with an error the CLI does not expect, for example HTTP 500. The message names the request.

Fix: run the command again in a few minutes, and check https://status.render.com.

### render_bad_response

Render sent an answer the CLI cannot read.

Fix: update the CLI and run the command again. If it keeps happening, email support@deplane.io with the message.

### render_import_refused

The report of `deplane import render` has a ✗ line: something stops the import, for example a database whose IP allow list does not let Deplane in (the line names the addresses to add), a suspended or expired database, a static site or worker given instead of the web service, a folder with no files, or a plan limit. Nothing was created on Deplane.

Fix: do what the ✗ lines say, then run the command again. See [Moving from Render](render.md#let-deplane-reach-the-database).

### missing_railway_project

`deplane import railway` needs the Railway project to import.

Fix: pass its name or ID, and the service after a slash if several have a public domain: `deplane import railway my-project/web --check`. See [Moving from Railway](railway.md).

### invalid_railway_project

The argument to `deplane import railway` is not a project, or `PROJECT/SERVICE`. It is not repeated in the message.

Fix: pass the project's name or ID as the Railway dashboard shows it, and the service after a slash.

### railway_token_missing

`deplane import railway` got no Railway token: nothing was piped in or typed at the prompt, and `RAILWAY_TOKEN` is not set. In the dashboard's **Import from another platform**, the same code means the token field was empty.

Fix: create a project token in the project's Settings → Tokens, then paste it at the hidden prompt, pipe it in, or set `RAILWAY_TOKEN`. There is no flag for it.

### railway_token_unreadable

What was piped into `deplane import railway` is not one token: it has spaces or several lines, or is too long. In the dashboard, it means what was pasted is not one token (several lines, spaces, or too long).

Fix: pipe in only the token, on one line.

### railway_token_invalid

Railway refused the token (HTTP 401): it is mistyped, expired or deleted. In the dashboard, the same code means the pasted token was refused; it is never shown back.

Fix: create a new project token in the project's Settings → Tokens and run the command again.

### railway_forbidden

Railway did not let the token read something the import needs ("Not Authorized"), or did not let it list projects to find one by name. The token may be wrong or expired, or reach another project or workspace.

Fix: use a project token of the project (its Settings → Tokens), or pass the project's ID (Settings → General) with an account token of a member of its workspace.

### railway_project_not_found

Railway has no project with that name or ID that the token can see, or the project token belongs to another project (the message names it).

Fix: check the name or ID in the Railway dashboard, and use a token of that project.

### railway_project_ambiguous

Several projects the token can see have that name.

Fix: pass the project's ID instead (its Settings → General shows it).

### railway_environment_ambiguous

The project has several environments and none is named `production`, and the token is not a project token, so the CLI cannot tell which to import.

Fix: use a project token for the environment to import (the project's Settings → Tokens): it reads that environment only.

### railway_service_not_found

The project has no service with that name in the environment. The message lists the services it has.

Fix: run `deplane import railway PROJECT/SERVICE` with one of them.

### railway_service_ambiguous

No service, or more than one, has a public domain, so the CLI cannot tell which is the web service to import.

Fix: name it: `deplane import railway PROJECT/SERVICE`. Import other web services as their own apps.

### railway_rate_limited

Railway's API limit for your account is used up for now (HTTP 429). Railway allows 100 calls an hour on its Free plan and 1000 on Hobby.

Fix: wait and run the command again. An import makes about 5 calls, plus 5 for each service.

### railway_unreachable

The CLI could not reach Railway's API (`backboard.railway.com`), or the answer was cut off.

Fix: check your internet connection and run the command again.

### railway_error

Railway's API answered with an error the CLI does not expect. The message names the request and Railway's message.

Fix: run the command again in a few minutes, and check https://status.railway.com.

### railway_bad_response

Railway sent an answer the CLI cannot read.

Fix: update the CLI and run the command again. If it keeps happening, email support@deplane.io with the message.

### railway_import_refused

The report of `deplane import railway` has a ✗ line: something stops the import, for example a Postgres without a public URL (add a TCP proxy to it: Settings → Networking → Public Networking), a folder with no files, or a plan limit. Nothing was created on Deplane.

Fix: do what the ✗ lines say, then run the command again. See [Moving from Railway](railway.md#before-you-start).

### dns_provider_unsupported

`deplane domains switch` does not know the provider `--provider` named. It knows cloudflare, route53, digitalocean, gandi, porkbun, godaddy and manual (by hand).

Fix: use one of those, or `--provider manual` to set the records by hand. See [Custom domains](domains.md#switch-dns-for-me).

### cloudflare_token_missing

`deplane domains switch` got no Cloudflare token: nothing was piped in, nothing was typed at the prompt, and `CLOUDFLARE_API_TOKEN` is not set.

Fix: set `CLOUDFLARE_API_TOKEN`, or pipe the token in. Create one at https://dash.cloudflare.com/profile/api-tokens with the "Edit zone DNS" template, for this zone only. There is no flag for it.

### cloudflare_token_unreadable

What was given as the Cloudflare token is not one token: it has spaces or several lines, or is too long.

Fix: pipe in or set only the token itself, as Cloudflare showed it when you created it.

### cloudflare_token_invalid

Cloudflare refused the token (HTTP 401): it is mistyped, expired or revoked, or it is the Global API Key, which `deplane domains switch` does not use.

Fix: create an API token with the "Edit zone DNS" template, for this zone only, and run the command again.

### cloudflare_forbidden

Cloudflare did not let the token make a request (HTTP 403): it lacks a permission, usually `Zone > DNS > Edit` for this zone.

Fix: use a token with `Zone > DNS > Edit` whose Zone Resources include the domain's zone.

### cloudflare_zone_not_found

None of the zones the token can see holds the domain.

Fix: check that the domain's DNS is on Cloudflare, under the account the token belongs to, and that the token's Zone Resources include that zone.

### cloudflare_zone_not_active

The domain's zone is on Cloudflare but not active (for example `pending`): its nameservers at the registrar are not Cloudflare's yet, so records changed there do nothing. `--check` shows the plan anyway; the switch refuses.

Fix: finish moving the nameservers to Cloudflare (its dashboard shows the two to set at your registrar), wait until Cloudflare says the zone is active, then run the command again.

### cloudflare_rate_limited

Cloudflare's API limit for the token is used up for now (HTTP 429). A switch makes about 10 calls.

Fix: wait five minutes and run the command again.

### cloudflare_unreachable

The CLI could not reach Cloudflare's API (`api.cloudflare.com`), or the answer was cut off.

Fix: check your internet connection and run the command again.

### cloudflare_error

Cloudflare answered with an error; the message quotes it. When it refused the switch's batch of changes at the domain, none of them was applied: the domain is as it was, and only the TXT record added before it stays.

Fix: read Cloudflare's message, fix the cause and run the command again. To remove the TXT record too, run the rollback command shown (`deplane domains switch DOMAIN --rollback FILE`). Cloudflare's status page: https://www.cloudflarestatus.com

### cloudflare_bad_response

Cloudflare sent an answer the CLI cannot read.

Fix: update the CLI and run the command again. If it keeps happening, email support@deplane.io.

### dns_rollback_unwritable

`deplane domains switch` saves the records as they are before it changes anything, to a file in the current folder, and could not write it. Nothing was changed on Cloudflare.

Fix: run the command from a folder you can write to.

### dns_switch_incomplete

The DNS switch stopped part way. This happens only when the zone cannot use Cloudflare's batch API, so the records were changed one by one and one of the writes failed (the message says which and why); the changes made before it stay, and are listed. It also covers Deplane not giving the domain's TXT value, before anything changed. With the batch API, a refused change leaves the domain as it was and reports Cloudflare's own error ([cloudflare_error](#cloudflare_error)).

Fix: put the records back with the command shown (`deplane domains switch DOMAIN --rollback FILE`), or fix the cause and run the switch again: it starts from the records as they are now.

### dns_txt_not_visible

The switch added the TXT record that proves the domain is yours, but public DNS (1.1.1.1, the resolver Deplane checks with) did not show it within 3 minutes, so the switch did not move traffic. Nothing at the domain itself changed. This is usually a negative answer cached by the resolver.

Fix: run the same command again in a few minutes; the TXT record stays, and is harmless. To remove it instead, run the rollback command shown. `--no-wait` skips this wait, but Deplane then may not verify the domain at once.

### dns_records_changed

The domain's records on Cloudflare changed between the preview and your answer, so the switch stopped before writing anything: the preview, and the rollback file, would not match the zone.

Fix: run the command again to see the new preview.

### dns_delegated

The domain, or a name between it and the zone, has `NS` records: it is delegated to other nameservers, so records written in this Cloudflare zone would do nothing.

Fix: set the records `deplane domains add` shows where the delegated name is served, by hand.

### cloudflare_too_many_records

Cloudflare listed more records for the domain's name than the CLI reads (5000), so it cannot see them all. It never plans or saves a rollback from a partial list, so nothing was changed.

Fix: set the records shown by `deplane domains add` by hand, or email support@deplane.io.

### dns_rollback_invalid

The file given to `--rollback` is not a rollback file from `deplane domains switch`, cannot be read, or names a record the switch does not manage.

Fix: pass the file the switch saved. Its name, `deplane-dns-DOMAIN-DATE.json`, was printed by the switch, in the folder it ran from.

### dns_rollback_mismatch

The rollback file is for another domain, or for a Cloudflare zone this token sees under a different id (the zone was deleted and added again, or the token belongs to another account).

Fix: pass the domain the file is for, or use a token for the account that holds that zone. If the zone was added again, set the records by hand from the file.

### dns_rollback_incomplete

The rollback failed. With Cloudflare's batch API, Cloudflare refused it and nothing changed; without it, it stopped part way when one of the writes failed.

Fix: fix the cause and run the same `--rollback` command again. It starts from the records as they are now, so running it twice is safe.

### dns_credentials_missing

The DNS switch needs your DNS provider's key and none was given: on the command line nothing was piped in and the provider's variables are not set; in the dashboard a key field is empty.

Fix: make the narrowest key the provider allows (see [Custom domains](domains.md#switch-dns-for-me)) and give it. It is used for the switch and never stored.

### dns_credentials_invalid

The DNS provider did not accept the key: it is wrong, expired or revoked, or (in the dashboard) it is not shaped like a key, or it fills a field that provider does not have.

Fix: create a new key as [Custom domains](domains.md#switch-dns-for-me) describes for your provider, and paste only the key itself.

### dns_provider_forbidden

The DNS provider accepted the key but refused it this call (HTTP 403): the key lacks a permission, or it is limited to other domains.

Fix: give the key the DNS permissions the switch needs, for this domain. [Custom domains](domains.md#switch-dns-for-me) lists them per provider.

### dns_api_refused

The DNS provider refuses its API for this domain or account: GoDaddy keeps its API for accounts with 10 or more domains, and Porkbun needs API Access switched on per domain.

Fix: on Porkbun, switch on API Access for the domain and try again. Otherwise use the by-hand mode (`deplane domains switch HOST --provider manual`, or "Set the records by hand" in the dashboard), which shows the records to set and watches for them.

### dns_zone_not_found

The key sees no zone (or domain) at the DNS provider that holds the hostname.

Fix: check that the domain's DNS is at that provider, under the account the key belongs to, and that the key may reach that domain.

### dns_provider_mismatch

The domain's nameservers belong to another provider than the one chosen, so records changed there would do nothing. The preview shows the plan anyway; the switch refuses.

Fix: choose the provider the nameservers name (the preview says which), or use the by-hand mode.

### dns_provider_rate_limited

The DNS provider's API limit for this key is used up for now.

Fix: wait five minutes and try again. A switch makes about ten calls.

### dns_provider_unreachable

Deplane could not reach the DNS provider's API, or its answer was cut off.

Fix: check the connection and try again in a few minutes.

### dns_provider_error

The DNS provider answered with an error; its message (without your key) is in the error.

Fix: read the provider's message and try again in a few minutes. If a switch stopped half way, roll it back first.

### dns_provider_bad_response

The DNS provider sent an answer Deplane cannot read.

Fix: try again, and update the CLI. If it keeps happening, email support@deplane.io.

### dns_provider_disabled

Deplane does not switch DNS at that provider yet: each provider is switched on after a test with a real account there.

Fix: choose another provider in the list, or set the records by hand.

### dns_records_unsupported

The hostname has records the switch cannot replace safely, for example a Route 53 record with a routing policy (weighted, latency, geolocation, failover), or it is a zone's root and Deplane's edge addresses are not known. Nothing was changed.

Fix: set the records `deplane domains add` shows by hand at your provider.

### dns_too_many_records

The DNS provider lists more records than Deplane reads for one name (5,000; 500 of one type at GoDaddy), or for the whole domain where the provider can only list it all, so Deplane cannot see them all and does not plan from a partial list. Nothing was changed.

Fix: set the records `deplane domains add` shows by hand, or email support@deplane.io.

### dns_switch_dashboard_only

The DNS switch that sends your DNS provider key to Deplane runs only in the dashboard, for a person signed in with a passkey; CLI tokens cannot use it.

Fix: use the domain's page in the dashboard, or run `deplane domains switch` on your own computer, where the key never leaves it.

### dns_switch_not_found

There is no DNS switch with that id for the domain: it never existed, or its 30 days are over (switches and the records they saved are deleted after 30 days).

Fix: start a new switch from the domain's page.

### dns_switch_not_yours

Someone else in your team started this DNS switch. Only they can move its traffic; they or a team owner can roll it back.

Fix: ask them, or a team owner.

### dns_switch_state

The DNS switch is not in a state that allows this: a switch of the domain is already in progress, it was rolled back already, or there was no TTL to lower.

Fix: reload the domain's page to see where the switch stands, and finish or roll it back first.

### domain_not_added

`deplane domains switch --lower-ttl` was run for a domain that is not on the app yet. The TTL step saves the records first, and its file can undo a later switch only if it knows the TXT value Deplane gives when the domain is added.

Fix: run `deplane domains add HOST --app APP`, then `--lower-ttl` again.

### dns_switch_expired

More than 15 minutes passed between your passkey and moving traffic, so traffic was not moved. The TXT record is in place and harmless.

Fix: roll the switch back (it removes the TXT record), then start the switch again.

### missing_fly_app

`deplane import fly` needs the Fly app to import.

Fix: pass its name, as `fly apps list` shows it: `deplane import fly my-app --check`. See [Moving from Fly.io](fly.md).

### invalid_fly_app

The argument to `deplane import fly` is not a Fly app name. It is not repeated in the message, in case it was a token.

Fix: pass the app's name: lowercase letters, digits and hyphens.

### fly_token_missing

`deplane import fly` got no Fly.io token: nothing was piped in or typed at the prompt, and `FLY_API_TOKEN` is not set. In the dashboard's **Import from another platform**, the same code means the token field was empty.

Fix: create a read-only token and pipe it in: `fly tokens create readonly --expiry 1h | deplane import fly APP --check`. You can also paste it at the hidden prompt or set `FLY_API_TOKEN`. There is no flag for it.

### fly_token_unreadable

What was piped into `deplane import fly` is not one token: it has more than the one space after `FlyV1`, several lines, or is too long. In the dashboard, it means what was pasted is not one token (several lines, spaces, or too long).

Fix: pipe in only the token, on one line, as `fly tokens create readonly` prints it.

### fly_token_invalid

Fly.io refused the token (HTTP 401): it is mistyped, expired or revoked. In the dashboard, the same code means the pasted token was refused; it is never shown back.

Fix: create a new one with `fly tokens create readonly --expiry 1h` and run the command again.

### fly_forbidden

Fly.io did not let the token read part of the app (HTTP 403), for example the names of its secrets: the token is for another organization.

Fix: use a token of the app's organization: `fly tokens create readonly --org ORG --expiry 1h`.

### fly_app_not_found

Fly.io has no app with that name that the token can see.

Fix: check the name with `fly apps list`, and that the token is for the app's organization.

### fly_org_not_found

Fly.io has no organization with that slug that the token can see. The dashboard lists the apps of one organization at a time; empty means your personal one.

Fix: check the slug with `fly orgs list`, and that the token is for that organization (`fly tokens create readonly --org ORG`).

### invalid_fly_org

The organization slug typed in the dashboard is not one: Fly.io slugs are lowercase letters, digits and hyphens.

Fix: type the slug as `fly orgs list` shows it, or leave the field empty for your personal organization.

### fly_toml_invalid

The folder's `fly.toml` is not valid TOML, so `deplane import fly` cannot read the processes, ports and release command from it. The error names the line, never a value.

Fix: fix that line, or remove `fly.toml` to import from the Machines' settings alone, then run the command again.

### fly_rate_limited

Fly.io's API limit is used up for now (HTTP 429). The Machines API allows about one call per second for each kind of request.

Fix: wait a minute and run the command again. An import makes about 6 calls to Fly.io.

### fly_unreachable

The CLI could not reach Fly.io's Machines API (`api.machines.dev`), or the answer was cut off.

Fix: check your internet connection and run the command again.

### fly_error

Fly.io's API answered with an error the CLI does not expect, for example HTTP 500. The message names the request.

Fix: run the command again in a few minutes, and check https://status.flyio.net.

### fly_bad_response

Fly.io sent an answer the CLI cannot read.

Fix: update the CLI and run the command again. If it keeps happening, email support@deplane.io with the message.

### fly_import_refused

The report of `deplane import fly` has a ✗ line: something stops the import. For example, `fly.toml` in the folder is another app's or cannot be read, the app serves no HTTP, a scheduled Machine's schedule cannot run on Deplane, the folder has no files, or a plan limit is reached. Nothing was created on Deplane.

Fix: do what the ✗ lines say, then run the command again. See [Moving from Fly.io](fly.md#check-first).

### missing_vercel_project

`deplane import vercel` needs the Vercel project to import.

Fix: pass its name or ID, with its team first if it belongs to one: `deplane import vercel my-team/my-app --check`. See [Moving from Vercel](vercel.md).

### invalid_vercel_project

The argument to `deplane import vercel` is not a project, or `TEAM/PROJECT`. It is not repeated in the message, in case it was a token.

Fix: pass the project's name or ID (`prj_...`) as the Vercel dashboard shows it. For a team's project, put the team's slug or ID (`team_...`) and a slash first.

### vercel_token_missing

`deplane import vercel` got no Vercel token: nothing was piped in or typed at the prompt, and `VERCEL_TOKEN` is not set. In the dashboard's **Import from another platform**, the same code means the token field was empty.

Fix: create a token in Vercel's Account Settings → Tokens, scoped to the project's team and with a short expiration. Then paste it at the hidden prompt, pipe it in, or set `VERCEL_TOKEN`. There is no flag for it.

### vercel_token_unreadable

What was piped into `deplane import vercel` is not one token: it has spaces or several lines, or is too long. In the dashboard, it means what was pasted is not one token (several lines, spaces, or too long).

Fix: pipe in only the token, on one line.

### vercel_token_invalid

Vercel refused the token (HTTP 401): it is mistyped, expired or deleted. In the dashboard, the same code means the pasted token was refused; it is never shown back.

Fix: create a new token in Account Settings → Tokens and run the command again.

### vercel_forbidden

Vercel did not let the token read part of the project (HTTP 403): the token is not scoped to the project's team, or the team was not named.

Fix: use a token scoped to the team, and name the team: `deplane import vercel TEAM/PROJECT`, or set `VERCEL_TEAM_ID`.

### vercel_project_not_found

Vercel has no project with that name or ID that the token can see, in the team the CLI asked for.

Fix: check the name in the Vercel dashboard. For a team's project, name the team (`TEAM/PROJECT` or `VERCEL_TEAM_ID`) and use a token scoped to it.

### vercel_team_not_found

Vercel has no team with that slug or ID that the token can see.

Fix: check the team's slug or ID (`team_…`) in the Vercel dashboard, and use a token scoped to that team.

### invalid_vercel_team

The team typed in the dashboard is not a Vercel team slug or ID.

Fix: type the team's slug or ID (`team_…`) as the Vercel dashboard shows it, or leave the field empty for a personal account.

### vercel_rate_limited

Vercel's API limit is used up for now (HTTP 429).

Fix: wait a minute and run the command again. An import makes about 5 calls to Vercel.

### vercel_unreachable

The CLI could not reach Vercel's API (`api.vercel.com`), or the answer was cut off.

Fix: check your internet connection and run the command again.

### vercel_error

Vercel's API answered with an error the CLI does not expect, for example HTTP 500. The message names the request.

Fix: run the command again in a few minutes, and check https://www.vercel-status.com.

### vercel_bad_response

Vercel sent an answer the CLI cannot read.

Fix: update the CLI and run the command again. If it keeps happening, email support@deplane.io with the message.

### vercel_import_refused

The report of `deplane import vercel` has a ✗ line: something stops the import. For example, a cron schedule Deplane cannot run, a folder with no files, or a plan limit. Nothing was created on Deplane.

Fix: do what the ✗ lines say, then run the command again. See [Moving from Vercel](vercel.md#check-first).

### missing_netlify_site

`deplane import netlify` needs the Netlify site to import.

Fix: pass its name or ID: `deplane import netlify my-site --check`. See [Moving from Netlify](netlify.md).

### invalid_netlify_site

The argument to `deplane import netlify` is not a site name (`my-site` or `my-site.netlify.app`) or ID. It is not repeated in the message, in case it was a token.

Fix: pass the name or ID as the site's Site configuration shows them.

### netlify_token_missing

`deplane import netlify` got no Netlify token: nothing was piped in or typed at the prompt, and `NETLIFY_AUTH_TOKEN` is not set. In the dashboard's **Import from another platform**, the same code means the token field was empty.

Fix: create a personal access token in Netlify (User settings → Applications → Personal access tokens, with a short expiration). Then paste it at the hidden prompt, pipe it in, or set `NETLIFY_AUTH_TOKEN`. There is no flag for it.

### netlify_token_unreadable

What was piped into `deplane import netlify` is not one token: it has spaces or several lines, or is too long. In the dashboard, it means what was pasted is not one token (several lines, spaces, or too long).

Fix: pipe in only the token, on one line.

### netlify_token_invalid

Netlify refused the token (HTTP 401): it is mistyped, expired or deleted. In the dashboard, the same code means the pasted token was refused; it is never shown back.

Fix: create a new personal access token and run the command again.

### netlify_forbidden

Netlify did not let the token read part of the site (HTTP 403): its user is not a member of the site's team.

Fix: use a personal access token of a member of the team.

### netlify_site_not_found

Netlify has no site with that name or ID that the token can see.

Fix: check the name in Netlify (the site's Site configuration), and that the token's user is in the site's team.

### netlify_rate_limited

Netlify's API limit is used up for now (HTTP 429).

Fix: wait a minute and run the command again. An import makes about 5 calls to Netlify.

### netlify_unreachable

The CLI could not reach Netlify's API (`api.netlify.com`), or the answer was cut off.

Fix: check your internet connection and run the command again.

### netlify_error

Netlify's API answered with an error the CLI does not expect, for example HTTP 500. The message names the request.

Fix: run the command again in a few minutes, and check https://www.netlifystatus.com.

### netlify_bad_response

Netlify sent an answer the CLI cannot read.

Fix: update the CLI and run the command again. If it keeps happening, email support@deplane.io with the message.

### netlify_import_refused

The report of `deplane import netlify` has a ✗ line: something stops the import. For example, a folder with no files or a plan limit. Nothing was created on Deplane.

Fix: do what the ✗ lines say, then run the command again. See [Moving from Netlify](netlify.md#check-first).

### missing_cpanel_host

`deplane import cpanel` needs your cPanel server with `--host`.

Fix: pass the server name from cPanel's address bar, for example `--host server1.host.example`. The CLI uses port 2083. See [Moving from cPanel](cpanel.md).

### invalid_cpanel_host

`--host` is not a server name: it has characters a host name cannot have.

Fix: pass only the name (and, if your host uses another port, `:PORT`), for example `--host server1.host.example`.

### missing_cpanel_user

`deplane import cpanel` needs your cPanel username with `--user`.

Fix: pass the username you sign in to cPanel with, for example `--user shop`.

### invalid_cpanel_user

`--user` is not a cPanel username.

Fix: cPanel usernames are lowercase letters and digits; pass yours as cPanel shows it (top right in cPanel).

### invalid_site

`--site` is not a domain name.

Fix: pass the site's domain as cPanel lists it under Domains, for example `--site example.com` (no `https://`).

### backup_not_found

The file given with `--backup` or `--db-dump` does not exist or cannot be opened.

Fix: pass the path of the backup you downloaded from cPanel (Backup, "Download a Full Account Backup"). `--db-dump` goes with `--backup`, for a home directory backup.

### backup_unreadable

The backup is not a cPanel backup (a `.tar.gz` archive), or `--db-dump` is not a `.sql` or `.sql.gz` file, or the archive is cut off.

Fix: download a new full account backup in cPanel and run the command again with `--backup FILE`. Nothing was created on Deplane.

### cpanel_token_missing

`deplane import cpanel` got no cPanel API token: nothing was piped in, `CPANEL_API_TOKEN` is not set, and there is no terminal to ask in.

Fix: create a token in cPanel (Security, Manage API Tokens; give it an expiry date), then pipe it in (`deplane import cpanel --host HOST --user USER < token.txt`) or set `CPANEL_API_TOKEN`. See [Moving from cPanel](cpanel.md#the-api-token).

### cpanel_token_unreadable

What was piped in is not one token: it has spaces or more than one line, or is too long.

Fix: pipe in only the token, on one line.

### cpanel_token_invalid

cPanel did not accept the token for that user: it is wrong, expired or revoked, or `--user` is not the account the token belongs to.

Fix: check `--user`, and create a new token in cPanel (Security, Manage API Tokens).

### cpanel_unreachable

The CLI could not reach cPanel at `https://HOST:2083`, or the server's certificate does not match the name.

Fix: check `--host`. Use the server's own name, the one in cPanel's address bar (for example `server1.host.example`), rather than your domain, whose certificate may not cover port 2083.

### cpanel_error

cPanel answered with an error the CLI did not expect, or did not list the account's domains.

Fix: run the command again in a few minutes. If it keeps happening, ask your host whether the cPanel API is enabled for your account.

### cpanel_bad_response

cPanel sent an answer the CLI cannot read. `--host` may point at something other than cPanel.

Fix: check that `--host` is your cPanel server, then run the command again. If it keeps happening, email support@deplane.io with the message.

### cpanel_import_refused

The report of `deplane import cpanel` has a ✗ line: for example no WordPress in the document root, a multisite network, a database on another server, a database over 5 GB, a plan without MySQL (Free), or an app name your team already uses. Nothing was created on Deplane.

Fix: do what the ✗ lines say, then run the command again. See [Moving from cPanel](cpanel.md#what-is-refused).

### cpanel_backup_failed

cPanel refused to make a backup, did not list your home directory, or the backup was not finished after 2 hours.

Fix: download a full account backup yourself in cPanel (Backup, "Download a Full Account Backup"), then run the command again with `--backup FILE`.

### cpanel_download_refused

cPanel made the backup in your home directory but does not let the API token download it (some servers allow downloads only from a signed-in browser).

Fix: download the backup yourself (cPanel, File Manager, your home directory), then run the command again with `--backup FILE`. Delete the backup from cPanel afterwards: it holds your whole account.

### cpanel_dump_missing

The backup holds no dump of the site's database. A home directory backup has no databases.

Fix: use a full account backup, or add the database's own backup (`DBNAME.sql.gz` from cPanel's Backup screen) with `--db-dump FILE`. Nothing was created on Deplane.

### cpanel_dump_unreadable

The database dump cannot be read (a quote that never closes, a statement over 32 MB), it does not start the way `mysqldump` or `mariadb-dump` write one (the CLI reads only their quoting), or it has no `options` table with the site's table prefix, so it is not this site's database.

Fix: check the table prefix in `wp-config.php`, download a new backup, and run the command again. Nothing was created on Deplane.

### cpanel_multisite

The database has a WordPress multisite network's tables (`wp_blogs`, `wp_site`). The import does not move networks yet.

Fix: nothing to do on your side for now; email support@deplane.io if you need a network moved. Nothing was created on Deplane.

### cpanel_site_empty

The backup holds no files of the site's document root.

Fix: check `--site`, and that the backup is of this account. Nothing was created on Deplane.

### cpanel_site_too_large

The site's files are over 4.5 GB, or one file is, which would leave too little of the app's 5 GB [disk](disks.md). The check happens while the backup is read, before anything is created.

Fix: delete what the site no longer needs; old backups, caches and log files inside `public_html` are common. Then run the command again.

### cpanel_database_too_large

The site's database is over 5 GB as cPanel reports it, or its dump is over 8 GB. A [MySQL](mysql.md) has 10 GB for data, indexes and temporary space.

Fix: delete what the site no longer needs (post revisions, spam comments, old log tables of plugins), make a new backup, and run the command again.

### site_import_failed

The new app's one-time import receiver did not answer, or refused a batch of files or the database reset. The app may be half-imported; the receiver is turned off when the command ends.

Fix: run the same command again: it replaces the app's files and database from the start. Check the app with `deplane status` and `deplane logs`. The message says how to delete what the import created.

### site_import_sql_failed

MySQL refused a statement of the site's dump while it was loaded. The message names the statement and MySQL's reason.

Fix: if the statement belongs to a plugin's table, remove or repair that table on the old site (or the plugin), make a new backup, and run the same command again.

### cpanel_dump_charset

The site's database dump is written in a character set the import does not read (for example `gbk` or `sjis`, whose characters can contain the bytes of a quote or a backslash). The import reads `utf8mb4`, `utf8`, `latin1` and `ascii` dumps.

Fix: convert the database to `utf8mb4` on the old host (most WordPress sites already are), make a new backup, and run the command again. Nothing was created on Deplane.

### cpanel_no_space

The CLI keeps the site's files and database dump in your computer's temporary folder while it copies them, and that folder's disk has too little free space.

Fix: free space there, or point `TMPDIR` at a folder on a disk with room (`TMPDIR=/Volumes/big/tmp deplane import cpanel ...`), then run the command again. Nothing was created on Deplane.

### cpanel_other_site

The app named with `--name` (or after the domain) was made by an earlier import of a different site or cPanel account, so its files and database are not replaced. Nothing was deleted.

Fix: pick the app that belongs to this site with `--name`, or a new name for a new app.

### cpanel_live_site

The app went live, at a `--cutover` or because it has a custom domain attached, and the command would replace its files and database with the cPanel copy: everything changed on Deplane since then would be lost. `--yes` alone does not do that.

Fix: if you mean it, run the command in a terminal and type the domain when asked, or pass `--replace-live`. A disk backup and a MySQL backup are taken for this run first either way (an older one is never used instead: [backup_too_soon](#backup_too_soon)); the command prints the restore commands. See [Moving from cPanel](cpanel.md#after-the-cutover).

### site_import_secret

`SITE_IMPORT_KEY_SHA256` and `SITE_IMPORT_UNTIL` arm a WordPress app's one-time import receiver; `SITE_IMPORTED_FROM` and `SITE_IMPORT_CUTOVER_AT` record which site an app was imported from and that it went live. Only `deplane import cpanel`, run by a person with their own login (or the dashboard), may set these four, or remove the last two: AI tools, CI tokens and platform tokens are refused. Removing the key and expiry (disarming) is open to everyone who can change secrets.

Fix: run `deplane import cpanel` yourself after `deplane login`. See [Moving from cPanel](cpanel.md).

### forms_unavailable

Forms are not set up on this server.

Fix: try again later. If it stays, contact support.

### forms_private

Form submissions hold your visitors' personal data, so AI tools (MCP and agent tokens), the assistant and support views can never read, export or delete them, or change where they are sent.

Fix: open them in the dashboard's **Forms** tab, or run `deplane forms submissions FORM` from your own login. See [Forms](forms.md).

### captcha_key_required

A form's CAPTCHA was turned on without a secret key, so every post would be refused.

Fix: create a free Turnstile widget in your Cloudflare account with your app's address and custom domains as hostnames, then paste its secret key in the Forms tab, or run `pbpaste | deplane forms captcha FORM on --secret -`. See [CAPTCHA](forms.md#captcha).

### invalid_captcha_secret

That is not a Cloudflare Turnstile secret key.

Fix: copy the secret key (not the site key) from your widget's page at Cloudflare, and pass it on stdin: `pbpaste | deplane forms captcha FORM on --secret -`. See [CAPTCHA](forms.md#captcha).

### missing_form

A `deplane forms` command needs the form's name.

Fix: pass it, for example `deplane forms submissions contact`. `deplane forms` lists the app's forms.

### missing_state

`deplane forms captcha` needs `on` or `off` after the form's name.

Fix: run `deplane forms captcha contact on` or `deplane forms captcha contact off`.

### secret_in_argument

A Slack URL, a webhook URL or a Turnstile secret was passed on the command line, where it would stay in your shell history.

Fix: pass `-` and the value on stdin, for example `pbpaste | deplane forms notify contact --slack -`, or `off` to remove it.

### empty_secret

Nothing was read from stdin for a flag given `-`.

Fix: pipe the value in, for example `pbpaste | deplane forms notify contact --slack -`, or pass `off` to remove it.

### one_stdin_value

`--slack -` and `--webhook -` both asked for stdin in one command; stdin holds only one value.

Fix: set them one at a time: `deplane forms notify contact --slack -`, then `deplane forms notify contact --webhook -`.

### too_many_arguments

`deplane forms delete` takes the form and at most one submission ID.

Fix: run `deplane forms delete contact ID` for one submission, or `deplane forms delete contact` for all of them.

### agent_not_allowed

Agent tokens (`deplane agent login`) reach only the endpoints an AI may use for its person: they cannot delete anything, manage tokens or team members, run commands, import databases, or confirm actions.

Fix: do it yourself with `deplane` after `deplane login`, or in the dashboard. See [Agents, CI, and scripts](agents.md#agent-tokens).

### agent_scope_missing

The agent token's role does not include what this endpoint needs. `viewer` reads, `deployer` also builds, redeploys and rolls back, `operator` also creates apps and databases, sets variables, scales, and adds domains and workers.

Fix: get a token with a role that does, for example `deplane agent login --role deployer`.

### agent_app_not_allowed

The agent token is limited to other apps (`--app`). A limited token reaches only its apps' endpoints, and `whoami`: not app or database lists, and no new apps.

Fix: get a token for this app with `deplane agent login --role ROLE --app NAME`, or one without `--app` for all the team's apps.

### invalid_agent_role

An agent token's role is `viewer`, `deployer` or `operator`.

Fix: pass one of them with `--role`.

### missing_role

`deplane agent login` needs `--role`.

Fix: pass `--role viewer`, `--role deployer` or `--role operator`.

### invalid_agent_name

An agent's name is up to 60 letters, digits, spaces, dots, dashes or underscores, starting with a letter or digit. It is shown on the approval page and in the email.

Fix: name it after the agent, for example `--name claude-code`.

### agent_ttl_too_long

An agent token lasts at most 30 days.

Fix: pass `--ttl 30d` or less, and run `deplane agent login` again when it expires.

### too_many_apps

An agent token can be limited to at most 20 apps.

Fix: leave `--app` out to allow all the team's apps.

### stack_file_missing

`deplane stack` found no `stack.yaml` in the current folder, or the file given with `-f` does not exist.

Fix: run the command in the folder with your `stack.yaml`, or pass it with `-f FILE`. See [Stacks](stacks.md) for how to write one.

### stack_invalid

The stack file cannot be read: it is empty, not valid YAML, holds more than one YAML document, has a key Deplane does not know (the message gives its line and the key you probably meant), or gives a value in a form Deplane does not read. `deplane stack check` also ends with this code when the file has ✗ lines.

Fix: fix the file at the line the message names, or do what the ✗ lines say, and run `deplane stack check` again. See [Stacks](stacks.md).

### stack_too_large

The stack is over a limit: the file is over 256 KB, it has more than 64 services or more than 64 engines, or applying it would take more than 2000 steps.

Fix: split it into several stacks. See [Limits](limits.md#stacks).

### stack_too_complex

The file nests deeper than 32 levels, uses anchors and aliases (`&`, `*`) more than 200 times, or grows past 20000 values or 512 KB once its aliases are expanded. Deplane refuses such a file before reading it.

Fix: remove deep nesting or repeated anchors and aliases; write the values out.

### stack_version

The file's `version` is not 1, the only stack file version there is.

Fix: set `version: 1`.

### invalid_stack_name

The stack's `name` is not a valid name.

Fix: use 3 to 40 characters: lowercase letters, digits and single hyphens, starting with a letter, for example `shop`.

### stack_empty

The stack has no services and no engines.

Fix: add at least one service or engine.

### duplicate_name

Two services or engines in the stack have the same name.

Fix: give every service and engine its own name, so references to it are clear.

### invalid_engine_name

An engine's name is not valid.

Fix: use 3 to 30 characters: lowercase letters, digits and single hyphens, starting with a letter, for example `shop-db`.

### engine_missing

An engine has no `engine:` kind.

Fix: add `engine: postgres`, `mysql`, `redis` or `clickhouse`.

### engine_unsupported

An engine's kind is not one Deplane runs.

Fix: use `postgres`, `mysql`, `redis` or `clickhouse`. Other databases are not offered yet.

### version_not_choosable

An engine other than Postgres has a `version:`. Only Postgres has a version to choose.

Fix: remove `version:`.

### source_choice

A service has no source, or more than one.

Fix: give it exactly one: `source: {image: REF}`, `source: {github: {repo: OWNER/NAME}}` or `source: {path: ./FOLDER}`.

### invalid_repo

A `github:` source's `repo` is not a GitHub repository name.

Fix: use `owner/name`, for example `acme/shop`.

### invalid_source_path

A `path:` source is outside the folder that holds `stack.yaml` (an absolute path, a path with `..` that leaves the folder, or a drive letter), or the folder does not exist.

Fix: use a folder inside the stack's folder, relative to `stack.yaml`, such as `./web`.

### source_path_server

A service builds from a `path:` folder, and the request did not come from the CLI, which is the only thing that can upload a folder.

Fix: run `deplane stack apply` from the folder that holds `stack.yaml`, or use an `image:` or `github:` source.

### invalid_release_command

A service's `release_command` is more than one line, or longer than 1000 characters.

Fix: put several steps in a script and run the script. See [Release command](release-command.md).

### invalid_label

A service's `label` is longer than 40 characters.

Fix: shorten it.

### private_network_sleeps

A service has `private_network: true` and a `sleep_after_minutes` other than 0. Other apps would find it asleep.

Fix: set `sleep_after_minutes: 0`, or turn `private_network` off.

### duplicate_domain

Two services of the stack list the same domain. A domain routes to one app.

Fix: keep it on one service.

### duplicate_process

A service has two workers or cron jobs with the same name.

Fix: rename one.

### unknown_engine

A service's `uses:` names an engine the stack does not have.

Fix: add the engine under `engines:`, or remove it from `uses:`.

### uses_service

A service's `uses:` names another service. `uses:` lists engines only.

Fix: to reach the other service, set a variable to `{from: SERVICE.private_url}` and turn on that service's `private_network`.

### two_engines_of_a_kind

A service uses two engines of the same kind. An app has one `DATABASE_URL`, one `MYSQL_URL`, one `REDIS_URL` and one `CLICKHOUSE_URL`.

Fix: use one, and reach the other through a second service.

### duplicate_variable

A variable is set twice in the same `env:` or `build_env:`.

Fix: keep one.

### attach_variable

`env:` sets `DATABASE_URL`, `MYSQL_URL`, `REDIS_URL` or `CLICKHOUSE_URL`, which the service's `uses:` already sets.

Fix: remove it from `env:`.

### invalid_value

A variable gives no form, or more than one of a value, `{generate: N}`, `{prompt: true}` and `{from: OBJECT.FIELD}`.

Fix: give exactly one, for example `SECRET: {generate: 48}`.

### invalid_generate

A `{generate: N}` length is outside 16 to 128.

Fix: use a length in that range, for example `{generate: 48}`.

### from_in_build

A `build_env:` variable uses `{from: ...}`. References are filled in when the app runs, not when it builds.

Fix: move the variable to `env:`.

### invalid_reference

A `{from: ...}` value is not `OBJECT.FIELD`, or names a field the object does not have.

Fix: use a field the message lists: for an engine, such as `shop-db.url` or `shop-db.host`; for a service, `url` or `private_url`. See [Stacks](stacks.md#variables).

### unknown_reference

A `{from: ...}` value names something the stack does not have.

Fix: reference a service or engine of this stack.

### private_network_off

A variable references `SERVICE.private_url`, and that service is not on the private network.

Fix: set `private_network: true` on that service.

### literal_secret

A warning: a variable whose name looks secret (`*_KEY`, `*_SECRET`, `*_TOKEN`, `*PASSWORD*` and similar) has its value written in the file.

Fix: use `{prompt: true}` (asked for when you apply) or `{generate: N}`, and keep secrets out of your repository.

### stack_managed_by_terraform

The stack was made with Terraform or OpenTofu, so a `stack.yaml` apply would undo it.

Fix: change it in your `.tf` files and run `tofu apply` (or `terraform apply`).

### name_taken

A stack names an app or database your team already has outside any stack, or a pull request preview, or one was created under that name by someone else while the stack was being applied.

Fix: rename it in the file, or apply with `--adopt` to make the existing one part of the stack (it is then changed to match the file). A preview's name cannot be adopted. See [Stacks](stacks.md#existing-apps-and-databases).

### in_another_stack

An app or database the file names belongs to another stack. An object is in one stack at most.

Fix: rename it in this file, or apply with `--move` to move it here from the other stack (with its values). Remove it from the other stack's file too.

### engine_immutable

The file changes an existing engine's kind, size or Postgres version. Deplane does not change, resize or upgrade a database in place.

Fix: keep the current setting in the file. To move to a new size or version, add a new engine, copy the data with [`deplane db import`](import-postgres.md), then point `uses:` at it.

### disk_immutable

The file changes the path of an app's existing disk. A disk cannot move.

Fix: keep the current path in the file.

### engine_attached

The file adds an engine to `uses:`, and the app already uses another engine of that kind.

Fix: detach the other one first (`deplane db detach`, `deplane redis detach`, `deplane mysql detach` or `deplane clickhouse detach`), or keep it in `uses:`.

### process_kind

The file turns an existing worker into a cron job, or a cron job into a worker.

Fix: give it a new name in the file.

### disk_kept

A warning: an app has a disk the file no longer lists. The apply keeps it, with its files.

Fix: delete it by hand if you no longer need its files: `deplane disks destroy --app APP`.

### attachment_kept

A warning: an app still uses an engine the file no longer lists in its `uses:`. It stays attached.

Fix: detach it by hand when the app no longer needs it.

### domain_removed

A warning: a domain of the app is no longer in the file. The apply removes it, and it stops serving.

Fix: keep it in the file if it should still serve.

### changed_outside

A warning: a variable the stack set was set by hand since the last apply. Deplane knows because each apply records a keyed fingerprint (HMAC) of every value it sets, never the value. An apply sets it back to what the file says only with `--yes`.

Fix: keep the change in the file instead, take the variable out of the file to manage it by hand, or apply with `--yes` to set it back.

### stack_changed_outside

The apply would set back variables that were changed by hand since the stack set them (⚠ `changed_outside` in the plan), and you did not say to.

Fix: put the new values in the file, or run `deplane stack apply --yes` (`overwrite: true` in the API) to set them back.

### stack_confirmation_required

The apply or destroy would delete apps or databases, with their data, and the request did not say which deletes the person confirmed.

Fix: send `deletes`, the list (kind/name) the plan shows, after the person confirmed it. The CLI does this once you type the stack's name.

### stack_plan_changed

What the apply or destroy would delete is not what you confirmed: something changed between the plan you saw and the apply.

Fix: run the command again and check the new list before typing the stack's name.

### set_in_both

A warning: a service's `deplane.toml` and `stack.yaml` both set the same field to different values. The stack's value is used.

Fix: remove the field from one of the two files.

### stack_apply_not_allowed

Whoever started the apply is no longer an active member of the team, or the token it was started with was revoked or expired. The apply stopped at its next step.

Fix: what it did so far is kept. A member can apply the stack again.

### moved_from

A warning: `--move` moves an app or database from another stack into this one, with its values and whether a stack created it. From then on this stack's file manages it.

Fix: remove it from the other stack's file too, or that stack's next plan refuses it ([in_another_stack](#in_another_stack)).

### left_in_place

A warning: an app or database is in the stack but no longer in the file. It keeps running and stays in the stack, and every plan shows it, until it is pruned or put back.

Fix: put it back in the file to manage it again, or apply with `--prune` to delete it (an object that joined with `--adopt` is released instead, never deleted).

### adopted_kept

A warning: an object no longer in the file joined the stack with `--adopt`, so `--prune` does not delete it. It is left running, outside the stack.

Fix: delete it by hand if you no longer need it.

### github_repo_not_granted

Deplane's GitHub App cannot reach the repository of a `github:` source for you, or your list of repositories is more than an hour old.

Fix: install the GitHub App on that repository, open the dashboard's GitHub page to refresh your repositories, then apply (or retry) again. See [GitHub](github.md).

### stack_does_not_fit

The stack does not fit your plan or your free room: the message says what it needs, for example "Needs 1 GB more memory; you have 512 MB free" or "Needs MySQL; Free does not include it". Nothing was changed.

Fix: make room by removing apps or databases you no longer need, use smaller sizes or fewer instances, or move to a larger plan. See [Limits](limits.md#plans).

### stack_cannot_apply

`deplane stack apply` stopped before changing anything: the plan has a ✗ line, or the stack does not fit your plan.

Fix: do what the ✗ lines say, then apply again. `deplane stack plan` shows the plan without applying.

### stack_prompt_missing

The stack asks for a value when it is applied (`{prompt: true}`), and none was given: neither `DEPLANE_STACK_<SERVICE>__<NAME>` nor `DEPLANE_STACK_<NAME>` is set and there is no terminal to ask on.

Fix: set `DEPLANE_STACK_<NAME>` (for example `DEPLANE_STACK_STRIPE_KEY`; in CI, from your CI's secret settings), or run the command in a terminal. See [Stacks](stacks.md#values-asked-for-when-you-apply).

### stack_prompt_unknown

An apply request gave a value for a variable the stack does not ask for.

Fix: give only the values the plan lists under `prompts`.

### stack_apply_running

The stack is already being applied, or destroyed. A stack has one apply at a time.

Fix: wait for that apply to finish or fail (`deplane stack status NAME`), then try again.

### stack_changed

The stack was applied, forgotten or created by someone else while this apply was being planned.

Fix: apply again.

### stack_apply_failed

A step of the apply failed. The message says which and why. Everything done before it is kept.

Fix: fix what the message says, then `deplane stack retry APPLY-ID`, or apply again.

### stack_apply_not_failed

Only an apply that failed can be retried; this one is running or done.

Fix: see where it is with `deplane stack status NAME`.

### stack_apply_not_latest

The apply you tried to retry is not the stack's newest. Retrying it would apply an older file and undo what later applies changed.

Fix: apply the stack again with `deplane stack apply`, or retry its newest apply (`deplane stack status NAME` shows it).

### engine_in_use

`--prune` would delete a database the stack created and the file no longer lists, or `deplane stack destroy` would delete one the stack created, but an app that stays (one outside the stack, or one the stack adopted) still uses it, so it is not deleted. The check runs when the plan is made and again right before the delete, so an app attached in between stops the apply at that step.

Fix: detach it from those apps first (`deplane db detach`, `deplane redis detach`, `deplane mysql detach` or `deplane clickhouse detach`), or keep it in the file; then prune or destroy again, or `deplane stack retry` the stopped apply.

### previews_removed

A warning: an app's GitHub connection has pull request previews on, and the stack file does not (previews are off unless `previews: true`). The apply connects the repository again with previews off, which deletes the app's preview apps and their databases, and deploys the branch's latest commit.

Fix: add `previews: true` under the service's `github:` source to keep them.

### process_kept

A warning: the app you adopt with `--adopt` has a worker or cron job that the file does not list. The adopting apply keeps it.

Fix: add it to the file to manage it there. From the next apply on, workers and cron jobs the file does not list are removed.

### domain_kept

A warning: the app you adopt with `--adopt` serves a custom domain that the file does not list. The adopting apply keeps it.

Fix: add it to the file under `domains:`. From the next apply on, domains the file does not list are removed.

### stack_retry_needs_values

The failed apply's remaining steps set values that were asked for when it was applied, and Deplane does not keep those.

Fix: apply the stack again: `deplane stack apply` asks for them.

### stack_value_missing

A value the apply needs is missing from the stack's stored values.

Fix: apply the stack again.

### stack_object_gone

An app of the stack was deleted while the stack was being applied.

Fix: apply again; the stack creates it again.

### stack_build_failed

The apply waits for each app's first build and release; a build failed.

Fix: see the build log with `deplane logs --app APP`, fix the code or Dockerfile, then apply again.

### stack_app_unhealthy

An app's new release did not pass its health check, so it did not start serving.

Fix: check its logs with `deplane logs --app APP` and its `health_check` and `port`, then apply again.

### stack_timeout

A new database of the stack took longer than 15 minutes to become available, or an app's first build and release took longer than 45 minutes.

Fix: retry with `deplane stack retry APPLY-ID`. If it keeps happening, email support@deplane.io.

### stack_not_found

Your team has no stack of that name.

Fix: see your stacks with `deplane stack list`.

### stack_apply_not_for_ai

AI tools cannot apply, retry, forget or destroy stacks: an apply can carry secrets and change many apps at once.

Fix: run `deplane stack apply` yourself.

### stacks_unavailable

Stacks are not available on this server.

Fix: try again later, or email support@deplane.io.

### too_many_stack_plans

Your team checked, planned or applied stacks 30 times in the last 10 minutes, the most allowed. `deplane stack apply` counts two.

Fix: wait a few minutes and try again. Logged out, `deplane stack check` checks a file on your computer without this limit.

### stack_body

A request to the stack API sent neither or both of `file` (the text of `stack.yaml`) and `model`.

Fix: send exactly one, for example `{"file": "version: 1\nname: shop\n..."}`.

### invalid_managed_by

A request to the stack API set `managed_by` to something other than `blueprint` or `canvas`. Stacks managed with Terraform are made by the Terraform provider, which is not released yet.

Fix: leave it out for `blueprint`.

### invalid_layout

A stack's canvas layout is not a JSON object, or is over 64 KB.

Fix: send the canvas's positions only.

### invalid_format

A stack export or conversion asked for a format Deplane does not write. Stacks export as `yaml` or as `hcl` (a Terraform file, see [Terraform and OpenTofu](terraform.md)).

Fix: leave out `--format` for yaml, or use `--format hcl`.

### missing_argument

The command needs a name or ID it was not given, for example `deplane stack status` without the stack's name.

Fix: run the command with it, as the message shows: `deplane stack status NAME` or `deplane stack retry APPLY-ID`. `deplane stack list` shows your stacks.

### redaction_unavailable

Before anything an AI reads leaves Deplane, the team's variable values are removed from it. This time Deplane could not read them to check, so nothing was sent.

Fix: try again in a moment. If it keeps happening, email support@deplane.io.

### assistant_no_app

The assistant changes things only for the app a question is about. This question was not about one app, so it can read and explain, not act.

Fix: ask from the app's page in the dashboard, or with `deplane ask --app NAME`.

### assistant_other_app

The assistant changes things only for the app this question is about, and its databases, Redis, MySQL and ClickHouse.

Fix: ask about the other app from its own page, or with `deplane ask --app NAME`.

### assistant_needs_confirmation

`deplane ask` ran without a terminal (in CI, a script, or an AI agent), so nobody could confirm a change. It took no action at all, so nothing is half done, and lists what it would do with the command for each.

Fix: run those commands yourself in a terminal, or ask again in a terminal and confirm them there.

## Community templates

Codes from publishing, checking, reviewing and deploying [community templates](templates.md#community-templates). The checks' codes (from `licence_unrecognised` on) appear on a version's check results, under Your listings in the dashboard and in `deplane community show`; the version's state is `checks_failed`. Fix the repository, then submit again.

### community_unavailable

Community templates are not available here: on a reseller's dashboard, or on a platform where they are not set up.

Fix: deploy from the template gallery, or use Deplane's own dashboard at https://app.deplane.io.

### community_publish_not_allowed

Your team cannot publish community templates. The message names the rule: publishing is for a person at their own login (not a CI token or an AI tool), confirming with a passkey, who is an owner or admin of a team on a paid plan, at least 30 days old, active and Deplane's own customer. Unpublishing needs an owner or admin too.

Fix: ask a team owner or admin to do it, or wait until the team meets the rule. See [Who can publish](templates.md#who-can-publish).

### community_publisher_name_invalid

The publisher name is not 2 to 40 letters, digits, spaces, dots and hyphens, or it contains a brand name. This protects people from impersonation.

Fix: pick a name like `Acme Labs`. If you own the brand, email support@deplane.io.

### missing_publisher

`deplane community claim` needs the publisher name shown on your listings.

Fix: pass `--publisher "Acme Labs"`.

### missing_repo

`deplane community claim` or `deplane community submit` was run without a repository.

Fix: pass it, for example `deplane community claim OWNER/REPO --publisher "Acme Labs"` or `deplane community submit OWNER/REPO@v1.0.0`.

### community_ref_missing

`deplane community submit` was given a repository without `@` and a branch or tag.

Fix: add the branch or tag, for example `deplane community submit OWNER/REPO@v1.0.0`.

### community_ref_not_allowed

A community version is a branch or a tag. A bare commit and a full reference name (`refs/…`) are refused: GitHub shows a fork's commits under the original repository's name, so only a branch or a tag is known to be the repository's own code.

Fix: push to a branch or a tag and submit that, like `OWNER/REPO@main` or `OWNER/REPO@v1.2.0`.

### community_repo_claimed

Another team has claimed this repository for the community listing, or its listing of it is active. A listing whose claim was released, or whose repository another listing now holds, cannot be relisted either.

Fix: if the repository is yours, email support@deplane.io.

### community_repo_mismatch

The submission names a listing of another repository.

Fix: submit the listing's own repository.

### too_many_community_claims

Your team holds 10 claims, the most it may.

Fix: let an unverified claim expire (7 days after it was made), then claim again.

### community_claim_missing

Your team has no live claim of this repository: it never claimed it, the claim expired unverified, an admin released it, or the claim was renewed with a new code after you pushed the old one.

Fix: claim it (`deplane community claim OWNER/REPO --publisher NAME`), put the code it prints in `deplane.template.json`, push, then submit.

### community_publisher_mismatch

The `deplane.template.json` at the commit you submitted does not carry your team's claim code in `publisher`. The fix in the message shows the line to add.

Fix: add `"publisher": "dpc_…"` with your code, push it to the branch or tag, then submit again.

### community_version_pending

The listing already has a version in checks or review. A listing has one at a time.

Fix: wait until it is reviewed, or until its checks fail, then submit again.

### too_many_community_submissions

Your team submitted 5 community versions in the last 24 hours, the most allowed.

Fix: submit again tomorrow.

### too_many_community_requests

A team and a person may each make 30 community claims, submissions and deploys in 10 minutes.

Fix: wait a few minutes and try again.

### community_listing_not_found

There is no listed community template with that ID: it was never listed, or it was unpublished or delisted. Your team sees its own listings in every state.

Fix: see the listed ones with `deplane community list`.

### missing_listing

A command that acts on a listing was run without its ID: `deplane community show`, `deplane community unpublish`, `deplane admin community delist`, `deplane admin community relist`, or `deplane launch --community` with nothing after it.

Fix: pass the listing's ID (`cml_…`), from `deplane community list`.

### community_template_delisted

The community template is no longer listed. Two cases:

- **A deploy:** the template was delisted or unpublished before your deploy's build started, so nothing of it was deployed. What the deploy made before is kept.
- **Your own listing:** Deplane delisted it, so your team cannot submit to it, unpublish it or have it approved again. The reason is shown under Your listings.

Fix: for a deploy, use **Delete all of it** (`deplane templates delete DEPLOY-ID`) and pick another template. For your listing, read the reason; if you think it is wrong, email support@deplane.io.

### community_deploy_interactive_only

A CI token or an AI tool asked to deploy a community template. Community templates are deployed by a person at their own login.

Fix: deploy it from the dashboard, or with `deplane launch --community ID` after `deplane login`.

### licence_unrecognised

The licence check found no licence file at the repository's root (`LICENSE…`, `LICENCE…` or `COPYING…`) that is one of the accepted licences: MIT, Apache-2.0, BSD-2-Clause, BSD-3-Clause, ISC, 0BSD, Unlicense, Zlib, MPL-2.0, LGPL-2.1, LGPL-3.0, GPL-2.0, GPL-3.0 or AGPL-3.0 (any `-only` or `-or-later` form). A licence in a subfolder or only in `package.json` does not count.

Fix: add the full text of one of them as `LICENSE` at the repository's root, then submit again.

### secret_found

The scan found a secret (a key, a token, a password) in the repository's source, or in the image for a file with `image`. The result names the file and line, never the value.

Fix: remove it from the repository, and revoke it: it was public. Then submit again. Generate secrets with `${secret:N}` in the file instead.

### test_deploy_failed

The test deploy failed: the build failed, or the app did not start. The reason says which step and why.

Fix: deploy the repository yourself (`deplane launch --repo OWNER/REPO@REF`) to see the full build log, fix it, then submit again. The test deploy has no internet: an app that downloads something when it starts fails here.

### test_deploy_timeout

The test deploy did not go live, answering its health path with a status below 500, within 15 minutes.

Fix: make the app listen on `$PORT` and answer `app.health` quickly, without the internet. Then submit again.

### image_vulnerable

The image the test deploy ran has HIGH or CRITICAL known flaws that have a fix. The reason names up to three.

Fix: update the base image and packages (rebuild with current versions), push, then submit again. Flaws without a fix do not fail the check; the reviewer sees them.

### scan_failed

A scan did not run to the end, so the check is an error, never a pass. This is usually on Deplane's side.

Fix: submit again. If it keeps failing, email support@deplane.io with the version's ID.

### check_timeout

A check did not finish within 15 minutes.

Fix: submit again. If it keeps happening, email support@deplane.io with the version's ID.

### check_error

Something went wrong on Deplane's side during a check.

Fix: submit again. If it keeps failing, email support@deplane.io with the version's ID.

### community_review_own

A platform admin tried to approve a version submitted by a team they belong to.

Fix: ask another platform admin to review it.

### community_version_not_in_review

The version is not waiting for review: its checks are still running or failed, or it was already approved or rejected.

Fix: see the queue with `deplane admin community review`.

### missing_version

An admin community command that acts on a version was run without its ID.

Fix: pass the version's ID (`cmv_…`), from `deplane admin community review`.

### community_reason_invalid

A rejection or a delisting needs a reason of 1 to 500 characters of plain text. The publishing team sees it.

Fix: say what the publisher must change, or which rule was broken.

### community_listing_not_delisted

`deplane admin community relist` was run on a listing that is not delisted.

Fix: nothing to relist.

### community_version_gone

The listing's approved version can no longer be deployed: its kept image was deleted 90 days after the listing was taken down. It cannot be relisted as it is.

Fix: the publishing team submits a new version.

### listing_not_listable

A version's checks stopped because its listing can no longer be listed: the team unpublished it, an admin delisted it, or the team was suspended. Nothing more of the version is built or tested.

Fix: if the listing is listed again, submit the version again.

### missing_claim

`deplane admin community release-claim` was run without the claim's ID.

Fix: pass the claim's ID (`ccl_…`). The publishing team sees it in `deplane community claim OWNER/REPO --publisher NAME --json`.

### community_claim_released

The claim was released already.

Fix: nothing to do.

### abuse_report_no_listing

**Delist template** was used on an abuse report whose address is not a community template's page.

Fix: suspend the app or the team instead, or delist the listing from Admin, Community or with `deplane admin community delist`.

## Pipeline deploys (GitLab CI and Bitbucket Pipelines)

### pipeline_not_trusted

The job's ID token was refused. Deplane gives no detail about which check failed; the app's activity log records the reason. Common causes: no trust for this repository on the app (`deplane pipelines list`), the ID token's audience is not your Deplane API URL, a tag pipeline, or a branch other than the deploy branch on a trust with previews off.

Fix: add a trust with `deplane pipelines trust`, and set the ID token's audience to your API URL (GitLab `id_tokens:`, Bitbucket `oidc:`).

### pipeline_exchange_unavailable

Deplane could not fetch the CI host's signing keys to check the ID token.

Fix: run the job again in a minute.

### pipeline_not_allowed

A pipeline token deploys its app (deploy branch) or the app's previews (other branches), and reads their builds and releases. Nothing else: no variables, scaling, rollback, tokens or other apps.

Fix: do it yourself with `deplane` after `deplane login`, or in the dashboard.

### pipeline_app_not_allowed

The pipeline is trusted by another app.

Fix: deploy the app that trusts this repository (`--app`), or add a trust to this app with `deplane pipelines trust`.

### pipeline_branch_not_allowed

Only the trust's deploy branch deploys the app; other branches deploy previews, and the deploy branch deploys no previews.

Fix: use `deplane deploy --preview N` on other branches, or deploy from the trust's branch.

### pipeline_token_required

Deploying a preview by merge or pull request number is for a pipeline job's own token.

Fix: run `deplane deploy --preview N` in the pipeline job. GitHub previews are built with `deplane previews build`.

### pipeline_trust_not_allowed

Pipeline trusts are added and removed by a person, from `deplane` after `deplane login` or the dashboard: not with a CI, agent, AI or pipeline token.

Fix: run `deplane pipelines trust` on your own machine; it asks for your passkey.

### pipeline_trust_exists

This app already trusts that repository.

Fix: remove the trust (`deplane pipelines remove ID`) and add it again to change its branch or previews.

### too_many_pipeline_trusts

An app can trust at most 3 pipelines.

Fix: remove one with `deplane pipelines remove ID` first.

### pipelines_unavailable

Pipeline deploys are not set up on this server.

Fix: use a CI token (`deplane tokens create`) instead.

### invalid_project_id

A GitLab trust names the project by its numeric ID, shown on the project's page, never by its path.

Fix: pass `--project 123456`.

### invalid_uuid

A Bitbucket trust needs the workspace and repository UUIDs, as `{xxxxxxxx-...}`.

Fix: copy them from Repository settings, OpenID Connect.

### invalid_full_name

A Bitbucket trust needs the repository's full name, `workspace/repository`: its workspace picks the ID token's issuer.

Fix: pass `--name` with it, as in the repository's URL.

### invalid_provider

A pipeline trust is for `gitlab` or `bitbucket`.

Fix: run `deplane pipelines trust gitlab ...` or `deplane pipelines trust bitbucket ...`.

### missing_branch

A pipeline trust needs its deploy branch.

Fix: pass `--branch main`, for example.

### missing_trust

`deplane pipelines remove` takes the trust's ID.

Fix: list them with `deplane pipelines list`.

### invalid_preview

`--preview` and `previews remove` in a pipeline take the merge or pull request's number.

Fix: pass `"$CI_MERGE_REQUEST_IID"` (GitLab) or `"$BITBUCKET_PR_ID"` (Bitbucket).

### preview_needs_pipeline

`deplane deploy --preview N` deploys from a GitLab CI or Bitbucket Pipelines job, with the job's ID token.

Fix: run it in the pipeline, with `DEPLANE_ID_TOKEN` (GitLab `id_tokens:`) or `BITBUCKET_STEP_OIDC_TOKEN` set and `DEPLANE_TOKEN` unset.

### image_in_pipeline

A pipeline job deploys its folder, not a ready-made image.

Fix: leave `--image` out in the pipeline job.

### invalid_path

`--path` is a folder inside the current one, such as `apps/web`.

Fix: pass a relative path without `..`.

## Connected GitLab projects

### git_connect_not_allowed

A GitLab token is your own credential: only you, from `deplane` after `deplane login` or the dashboard, can connect or disconnect a project. CI, agent, AI and pipeline tokens cannot.

Fix: connect it in the dashboard: the app's Settings, GitLab.

### git_not_connected

The app is not connected to a GitLab project, or was disconnected.

Fix: connect a project in the app's Settings, GitLab.

### missing_token

Connecting needs a token, or, on a connected app, the webhook's signing token.

Fix: paste a fine-grained personal access token limited to the project.

### invalid_token

That is too long to be a token.

Fix: paste the token alone.

### token_refused

The host refused the token, or it cannot read the project or repository.

Fix: on GitLab, check the token is active and limited to this project, and that your account is Developer or higher in it. On Bitbucket, check it is an active repository access token of this repository, with Repositories: Read and Pull requests: Read.

### token_not_fine_grained

Deplane takes only a fine-grained personal access token, never a legacy one (which reaches all your projects).

Fix: make a fine-grained token in GitLab, User settings, Access tokens, limited to the one project.

### token_inactive

The token is revoked or expired.

Fix: make a new fine-grained token and connect again.

### token_permissions

On Bitbucket: the repository access token has a scope beyond Repositories: Read and Pull requests: Read (any write, admin, webhook or pipeline scope). On GitLab: The token's permissions are not exactly the ones Deplane needs: Project Read, Repository Read, Branch Read, Commit Read, Merge Request Read, Work Item Read, Create and Update, Commit Status Create, and on the User tab Personal Access Token Read, Rotate and Revoke. Anything more, Push above all, is refused, and so is anything less. A connected app is disconnected when its token's permissions change.

Fix: make a token with exactly those permissions.

### token_wrong_project

The token is limited to another project than the one you named.

Fix: limit the token to this project, or name the project the token is for.

### token_too_broad

On Bitbucket: the token lists more than one repository. On GitLab: The token reaches more than the one project: a second project, a group, or all your projects.

Fix: limit "Group and project access" to this one project.

### token_expiry

The token has no expiry date, or expires in more than 90 days. Deplane renews it every 7 days.

Fix: make a token that expires in 90 days or less.

### bad_signature

A GitLab webhook delivery is not signed with the connection's signing token, or is more than 5 minutes old. Deliveries with only `X-Gitlab-Token` are refused.

Fix: paste the webhook's signing token in the app's Settings again.

### git_branch_missing

The connected branch is not in the GitLab project.

Fix: push the branch, or connect another one in the app's Settings.

### git_root_missing

The root folder is not in the project at this commit.

Fix: check the root folder in the app's Settings.

### gitlab_deploy_failed

Deplane could not deploy the connected branch; the message says why.

Fix: fix the problem on GitLab or in the app's Settings, then run `deplane gitlab deploy` again.

### gitlab_deploy_slow

GitLab's commit did not reach Deplane within 2 minutes.

Fix: run `deplane status` in a minute; the deploy may still start.

### git_other_host

The app is already connected to another host (GitHub, GitLab or Bitbucket). An app deploys from one repository, so pushes to two never replace each other's releases.

Fix: disconnect it from the other host in the app's Settings first.

## Connected Bitbucket repositories

### invalid_repository

The Bitbucket repository is not written `workspace/repository`.

Fix: copy it from the repository's address on bitbucket.org, for example `acme/web`.

### token_not_repo_token

Deplane takes only a Bitbucket repository access token (it reaches one repository), never an app password, an API token, or a workspace or project access token.

Fix: make one in the repository's Repository settings, Access tokens, with only Repositories: Read and Pull requests: Read.

### token_wrong_repo

The token is for another repository than the one you named.

Fix: make the token in this repository's settings, or name the repository the token is for.

### bitbucket_deploy_failed

Deplane could not deploy the connected branch; the message says why.

Fix: fix the problem on Bitbucket or in the app's Settings, then run `deplane bitbucket deploy` again.

### bitbucket_deploy_slow

Bitbucket's commit did not reach Deplane within 2 minutes.

Fix: run `deplane status` in a minute; the deploy may still start.

## Stack sync on push and pull request environments

### stack_sync_needs_person

Turning a stack's sync on, changing it or turning it off was asked by a CI token, a pipeline or an AI tool. Later applies run as the person who turns sync on, so it is a person's act.

Fix: run `deplane stack sync on NAME` from your own machine (`deplane login`), or use the dashboard.

### stack_sync_not_found

The stack does not sync on push.

Fix: turn it on with `deplane stack sync on NAME --repo OWNER/NAME`.

### stack_sync_environment

The stack is a pull request environment. Its parent stack's sync makes and updates it; it has no sync of its own.

Fix: turn sync on for the stack it copies.

### stack_sync_not_blueprint

Only a stack applied from a `stack.yaml` syncs on push. This one is managed on the canvas or with Terraform.

Fix: apply it from a `stack.yaml` first, then turn sync on.

### stack_sync_path_source

A service of the stack builds from a folder (`source: {path: ...}`), which only the CLI can upload. A push cannot.

Fix: give that service an image or a repository source, apply, then turn sync on.

### stack_sync_webhook_secret

A webhook secret was sent for a sync that does not take one: only a GitLab sync takes the secret you paste from GitLab. Bitbucket's is made by Deplane, and GitHub needs none.

Fix: leave the secret out.

### stack_sync_unavailable

Stack sync, or the git host it needs, is not available on this server.

Fix: try again later, or email support@deplane.io.

### invalid_stack_path

The stack file's path is not a file path in the repository: empty, absolute, with `..`, or too long.

Fix: use a path from the repository's root, such as `stack.yaml` or `deploy/stack.yaml`.

### branch_required

A GitLab or Bitbucket source in `stack.yaml`, or a GitLab or Bitbucket sync, must name its branch: Deplane cannot read a repository's default branch before it is connected.

Fix: add `branch: main` (or your branch) to the source, or `--branch main` to `deplane stack sync on`.

### git_unavailable

The stack connects a service to GitLab or Bitbucket, and that host is not available on this server.

Fix: use an image source, or try again later.

### stack_host_token_missing

The apply connects services to GitLab or Bitbucket and needs a token for that host, limited to the repository.

Fix: give it when `deplane stack apply` asks, or set `DEPLANE_STACK_GITLAB_TOKEN` or `DEPLANE_STACK_BITBUCKET_TOKEN` where the CLI runs.

### stack_host_token_unknown

A token was given for a host the apply connects nothing to.

Fix: give only the tokens the plan lists under `host_tokens`.

### stack_is_environment

That stack is a pull request environment (its name ends in `-pr-` and a number). Its sync applies it from the pull request; nobody applies, forgets or destroys it by hand.

Fix: push to the pull request's branch to update it, or close the pull request (or run `deplane stack env delete NAME`) to delete it.

### stack_syncs

The stack syncs on push. Forgetting or destroying it would leave its sync and its pull request environments behind.

Fix: turn its sync off first (`deplane stack sync off NAME`), which deletes its pull request environments, then try again.

### stack_sync_change

The change would leave pull request environments behind: another repository (its pull requests are other ones), or environments turned off.

Fix: turn the sync off first (`deplane stack sync off NAME`, which deletes the environments), then on again with the new setting.

### stack_sync_turning_off

The stack's sync is being turned off: its pull request environments are being deleted, one by one.

Fix: try again in a few minutes.

### stack_environments_full

Your team has as many pull request environments as its plan allows (Free 0, Hobby 1, Pro 3, Team 10, Enterprise 25).

Fix: close another pull request, or move to a larger plan; then push to this one.

### stack_environments_off

The stack's sync no longer makes pull request environments (it was stopped or turned off while this one was being made).

Fix: turn sync on with `--environments`.

### sso_not_on_plan

Single sign-on is on the Enterprise plan. Contact support to move your team.

### sso_not_set_up

That team has no [single sign-on](sso.md), or the name is wrong. Check the team's short name, or sign in another way.

### sso_metadata_invalid

The identity provider's metadata can't be used; the message says why. Download the SAML metadata XML from your identity provider's app and try again.

### invalid_email_attribute

The email attribute name is not valid. Use the attribute's name as your identity provider sends it.

### invalid_required

Send `{"required": true}` or `{"required": false}`.

### sso_failed

Your company's sign-in did not complete. Start again. If it keeps failing, an owner can see the reason in **Activity**.

### sso_not_member

Your company's sign-in worked, but this account is not in the team. Ask an owner to invite you.

### sso_linked_elsewhere

This company account is linked to another Deplane account. An owner can clear the link on the Members page.

### sso_other_account

You are signed in to Deplane as someone else. Sign out first.

### sso_required

This team requires single sign-on. Sign in through your company.

### sso_test_first

Run a test sign-in with the current settings before making single sign-on required.

### sso_test_other_account

The test signed in as a different person. Sign in to your identity provider with your own account, then test again.

### sso_ci_owners_only

While single sign-on is required, only the team's owners can create CI tokens.

### sso_test_failed

An owner's test sign-in did not work; the message says why (for example the assertion is not signed, or the ACS URL differs). Fix it in your identity provider, then test again.

### sso_no_second_factor

Your account has no passkey or authenticator app yet, so it can't be signed in through your company. Open your invitation link, or sign in with an email link, set up a passkey, then use single sign-on.

### variable_groups_person_only

Variable groups are read and changed only by a person. CI tokens, agent tokens and AI tools cannot use them.

Fix: run the command yourself after `deplane login`, or use the dashboard.

### invalid_variable_group_name

Variable group names are 3 to 40 characters: lowercase letters, digits, and single hyphens, starting with a letter and not ending with a hyphen.

Fix: pick a name like `shared-config`.

### variable_group_exists

The team already has a variable group with this name.

Fix: pick another name, or change that group with `deplane groups set`.

### variable_groups_limit

A team can have 50 variable groups.

Fix: delete a group the team no longer uses with `deplane groups delete NAME`.

### variable_groups_per_app_limit

An app can use 10 variable groups.

Fix: detach a group from the app first.

### variable_group_in_use

Apps still use this variable group, so it was not deleted. The message names them.

Fix: detach it from each with `deplane groups detach NAME --app APP`.

### variable_group_clash

Another variable group the app uses already sets this name in the same scope. Nothing was changed.

Fix: keep each name in one group: remove it from one of them, or set it on the app itself.

### variable_group_attached

The app already uses this variable group.

Fix: nothing to do.

### variable_group_not_attached

The app does not use this variable group.

Fix: run `deplane secrets list` to see the groups it uses.

### variable_group_preview

A preview copies its app's variables, groups included, at each push, so it cannot use a group itself.

Fix: attach the group to the app the preview belongs to.

### too_many_variables

A [variable group](variable-groups.md) can hold 200 variables of each kind, and an app can get 500 of each kind, its own and its groups' together. Nothing was changed.

Fix: remove variables you no longer need, or detach a group from the app.
