Errors
Every failure comes back as a structured object written for the agent that will fix it: cause first, then the fix. Never only a log dump.
The AgentError shape
| Field | Type | Meaning |
|---|---|---|
status | "failed" | "needs_input" | failed: something broke. needs_input: a secret is missing; nothing broke. |
stage | string | Where it happened: upload, detect, plan, provision, build, migrate, release, return, or auth, limits, env, domain, db, rollback. |
service | string? | The service it happened in, e.g. api. |
code | string | Stable machine code. Safe to branch on. Every code has an anchor on this page. |
cause | string | What went wrong, in one sentence, naming the package, file, port or variable. |
file | string? | File and line when it can be extracted, e.g. payments.py:3. |
fix | string | What to do next, written as an instruction. |
retryable | boolean | true when calling deploy again after the fix can succeed. |
missing | MissingSecret[]? | For needs_input: each secret's name, service and the lines that read it. |
upgrade | UpgradeHint? | When the fix is a plan upgrade: trigger, one-sentence message, plan and payment link. |
logTail | string[]? | The last relevant log lines (up to 30), only for errors the library does not know yet. |
docs | string? | Link to this page at the code's anchor, e.g. /docs/errors#missing_python_module. |
Examples
A build or runtime failure, as the known-error library returns it:
{
"status": "failed",
"stage": "release",
"service": "api",
"code": "missing_python_module",
"cause": "Python module 'stripe' not found (imported in payments.py:3)",
"file": "payments.py:3",
"fix": "Add 'stripe' to requirements.txt (or pyproject.toml dependencies) of the 'api' service, then call deploy again",
"retryable": true,
"docs": "https://rivtor.com/docs/errors#missing_python_module"
}A missing secret. Nothing is broken; the agent asks the user once:
{
"status": "needs_input",
"stage": "plan",
"code": "missing_secrets",
"cause": "The app reads a secret that is not set: STRIPE_SECRET_KEY",
"fix": "Ask the user for STRIPE_SECRET_KEY, call env_set with them, then call deploy again.",
"retryable": true,
"missing": [
{ "name": "STRIPE_SECRET_KEY", "service": "api",
"usedIn": ["api/payments.py:3"] }
]
}The self-healing loop
- The agent calls
deploy. - Rivtor returns
failedwith the stage, cause, file and fix, orneeds_inputwith the missing secrets. - The agent edits the code, or asks the user for the secret and calls
env_set. - The agent calls
deployagain. Only services whose files changed rebuild, so each loop takes under a minute.
How a log becomes an error
Raw build and runtime output goes through the known-error library. Patterns registered for the failing stage are tried first, in library order, then every other pattern, then patterns chosen by exit code (137 out of memory, 139 segfault). The first match produces a cause and fix specific to your log: the package name, the file and line, the port, the variable. Secrets are redacted. Anything the library does not recognise comes back as unknown with logTail.
Build and runtime codes
All 71 codes in the library, plus unknown. The fix you receive is written for your exact log; the title here is the general case.
Databases, Redis and migrations
| Code | What it means | Stages |
|---|---|---|
data_service_not_provisioned | Database/Redis/S3 env var missing | any |
db_auth_failed | Database authentication failed | any |
db_connection_refused | Cannot connect to the database | any |
db_schema_missing | Table does not exist (migrations not run) | release |
prisma_migration_failed | Prisma migration failed | migrate, release |
alembic_migration_failed | Alembic migration failed | migrate, release |
django_migration_failed | Django migration failed | migrate, release |
migration_failed | Migration command failed | migrate |
celery_broker_unreachable | Celery cannot reach its broker | release, migrate |
redis_connection_refused | Cannot connect to Redis | any |
Node.js, Next.js and bundlers
| Code | What it means | Stages |
|---|---|---|
lockfile_missing | npm ci without a lockfile | build |
lockfile_out_of_date | Lockfile out of sync with package.json | build |
npm_peer_conflict | npm peer dependency conflict | build |
npm_package_not_found | npm package or version does not exist | build |
node_version_mismatch | Node.js version not supported | build, release, migrate |
native_module_build_failed | Native npm module failed to compile | build |
next_missing_suspense | useSearchParams() not wrapped in Suspense | build |
next_dynamic_server_usage | Page uses dynamic APIs during static generation | build |
next_static_export_unsupported | Feature not supported with output: 'export' | build |
next_prerender_error | Next.js failed to pre-render a page | build |
eslint_build_failure | ESLint errors fail the build | build |
vite_unresolved_import | Bundler could not resolve an import | build |
typescript_error | TypeScript type error | build |
node_esm_cjs_mismatch | ES module / CommonJS mismatch | build, release, migrate |
prisma_client_not_generated | Prisma client not generated | build, release, migrate |
node_entry_not_found | Start file does not exist | release, migrate |
node_local_import_not_found | Relative import points to a missing file | build, release, migrate |
missing_node_module | Node package not installed | build, release, migrate |
missing_build_script | No build script | build |
missing_start_script | No start script | build, release, migrate |
static_output_missing | Static build output folder not found | build |
Python and Django
| Code | What it means | Stages |
|---|---|---|
missing_requirements_file | requirements file not found | build |
python_version_incompatible | Python version not supported | build |
pip_resolution_conflict | Python dependency conflict | build |
python_package_not_found | Python package or version does not exist | build |
python_wheel_build_failed | Python package failed to build from source | build |
python_syntax_error | Python syntax error | build, release, migrate |
asgi_app_not_found | uvicorn/gunicorn could not load the app | release, migrate |
missing_python_module | Python module not installed | build, release, migrate |
python_import_error | Python ImportError (name not found) | build, release, migrate |
django_disallowed_host | Django rejects the host header | release, migrate |
django_csrf_origin | Django CSRF origin check failed | release, migrate |
django_improperly_configured | Django settings error | build, release, migrate |
Go and Rust
| Code | What it means | Stages |
|---|---|---|
go_version_mismatch | Go toolchain too old | build |
go_module_missing | Go module missing from go.mod / go.sum | build |
go_compile_error | Go compile error | build |
rust_toolchain_too_old | Rust toolchain too old for a dependency | build |
rust_compile_error | Rust compile error | build |
Dockerfile and builders
| Code | What it means | Stages |
|---|---|---|
dockerfile_copy_failed | Dockerfile COPY/ADD source not found | build |
dockerfile_syntax_error | Dockerfile parse error | build |
docker_base_image_not_found | Base image not found | build |
railpack_no_start_command | Builder could not find a start command | build |
railpack_unsupported | Builder could not detect the language | build |
Runtime, ports and platform
| Code | What it means | Stages |
|---|---|---|
out_of_memory | Process ran out of memory (also exit code 137) | build, release, migrate |
build_timeout | Build exceeded the time limit | build |
file_watcher_limit | Dev server / watch mode running in production | build, release, migrate |
disk_full | No disk space left | any |
segfault | Process crashed with a segmentation fault (also exit code 139) | build, release, migrate |
port_in_use | Port already in use | build, release, migrate |
dev_server_in_production | Dev server used as the start command | release, migrate |
wrong_port | App listens on a different port than expected | release, migrate |
bound_to_localhost | App listens on 127.0.0.1 instead of 0.0.0.0 | release, migrate |
health_check_timeout | App never answered the health check | release, migrate |
crlf_line_endings | Script has Windows (CRLF) line endings | build, release, migrate |
exec_format_error | Binary built for the wrong platform | build, release, migrate |
permission_denied | Permission denied | build, release, migrate |
command_not_found | Command not found | build, release, migrate |
missing_env_at_build | Environment variable missing at build time | build |
missing_env_var | Environment variable missing at runtime | release, migrate, provision, plan, detect, upload, return |
missing_system_library | Missing system shared library | build, release, migrate |
registry_network_error | Transient network error while downloading dependencies | build |
unknown | Not in the library yet. The cause quotes the most useful error line, logTail carries the last 30 relevant lines, and the fix says where to look for this stage. | any |
Platform codes
Returned by the API, the MCP servers and the CLI themselves rather than read from a log. Plan limits use HTTP 402 and include an upgrade hint with a payment link.
| Code | When | Fix |
|---|---|---|
unauthorized | No token, or the token is invalid, expired or revoked. | Run rivtor login or create a new token at /dashboard/tokens. |
token_expired | The API token has expired. | Create a new token and update RIVTOR_TOKEN or your MCP config. |
not_logged_in | CLI or local MCP server has no token. | Run rivtor login, or set RIVTOR_TOKEN. |
forbidden | Your role on a shared project does not allow this action. | Ask the project owner. |
too_many_auth_failures | Too many failed sign-ins from one address. | Wait, then retry with a valid token. |
rate_limited | Too many requests in a short window. | Wait a moment and retry. |
project_limit | HTTP 402. The plan's project limit is reached. | Delete a project or follow the upgrade link in the error. |
service_limit | HTTP 402. The app has more services than the plan allows per project. | Merge services, or upgrade. |
domain_limit | HTTP 402. The plan's custom-domain limit is reached. | Remove a domain, or upgrade. |
teammates_not_included | HTTP 402. Inviting teammates needs Pro or Team. | Upgrade to invite teammates. |
always_on_not_included | HTTP 402. Free apps sleep after an hour idle. | Upgrade to Hobby or above for always-on. |
verification_required | Always-on or a custom domain needs phone or card verification first. | Verify your account in the dashboard. |
missing_secrets | status needs_input: the code reads secrets that are not set. | Ask the user once, call env_set, deploy again. |
nothing_to_deploy | No deployable app was found in the uploaded files. | Deploy the folder that contains the app's manifest, or add a deploy.toml. |
source_too_large | Inline files total more than 2 MB (remote deploy). | Use the local server or the CLI, which upload a tarball (300 MB limit). |
missing_source | A deploy request had no source. | Pass path (local), or git_url, starter or files (remote). |
invalid_git_url | git_url is not a valid public https URL. | Use a URL like https://github.com/user/repo. |
project_name_taken | The project slug belongs to another account. | Pick another slug with --project or rivtor.json. |
project_suspended | The project is suspended pending abuse review. | Write to abuse@rivtor.com. |
provision_failed | Creating Postgres, Redis or storage failed. | Retry the deploy; if it repeats, contact support. |
wait_timeout | The deployment is still running after the wait limit. | Follow it with status or logs using the deploymentId. |
env_read_only | Tried to change a credential Rivtor manages (DATABASE_URL, REDIS_URL, S3_*). | Leave it; Rivtor injects and rotates it. |
invalid_env_key | An env var name is not valid. | Use letters, digits and underscores, not starting with a digit. |
domain_taken | The domain is already attached to another project. | Remove it there first. |
reserved_hostname | The hostname is a rivtor.com app address. | Those are assigned automatically; attach your own domain. |
platform_hostname | The hostname belongs to Rivtor. | Attach a domain you own. |
nothing_to_roll_back | There is no earlier release. | Deploy again instead. |
release_expired | That release's files were garbage-collected. | Roll back to a newer release, or redeploy. |
no_database | The project has no Postgres database yet. | Deploy code that uses Postgres, or set data = ["postgres"] in deploy.toml. |
sql_too_long | A db query is longer than 20,000 characters. | Shorten the query. |
network_error | The CLI could not reach the API. | Check your connection and RIVTOR_API_URL. |
Plan limits behind the 402 codes are on Limits.