Skip to content

Errors

Every error is a problem details document (RFC 9457), sent as application/problem+json. Its code is stable and made for code to act on. Its type links to the code's section on this page.

One answer is an HTML page instead: the limit in front of the API answers 429 without problem details. See Rate limits.

{
  "type": "https://docs.hosthatch.com/api/errors#validation_error",
  "title": "Validation failed",
  "status": 400,
  "detail": "One or more fields are invalid.",
  "code": "validation_error",
  "instance": "/api/v1/projects/acme/servers/774736/",
  "errors": [
    {"field": "hostname", "code": "invalid", "message": "Enter a valid hostname (letters, numbers, hyphens, and dots). Labels cannot start or end with a hyphen."}
  ]
}
Field Description
type A link to this page's section for the code.
title A short summary of the code.
status The HTTP status.
detail A sentence for people. It can change, so don't act on it.
code The stable code, one of those below.
instance The path of the request.
errors On validation_error only: each problem, with its field (null for the whole request), a code and a message.

Some errors add a member that names a resource: action_id, order_id, key_id, group_id, rule_id or servers. Each code's section says when.

Handle errors

  • Act on code. Don't parse detail or title.
  • A 4xx usually means the request has to change, and sending it again unchanged gets the same answer. Some describe a state that passes with time, such as 409 action_in_progress, 429 rate_limited, 403 project_not_ready and 409 insufficient_capacity. Each code's section below says whether waiting helps.
  • A 5xx is worth retrying after a short wait. Repeat an action or an order with the same Idempotency-Key, so it can't happen twice. Before you repeat any other write, check whether the first one went through, unless its page says it is safe to send again.
  • When there is a Retry-After header, wait that many seconds.
  • New codes can appear in v1. Treat a code you don't know by its HTTP status.
  • Check the Content-Type before you parse the body as problem details, because of that one HTML answer.

Codes

Code Status Title
validation_error 400 Validation failed
feature_unavailable 400 Feature unavailable
authentication_required 401 Authentication required
invalid_api_key 401 Invalid API key
api_key_expired 401 API key expired
permission_denied 403 Permission denied
insufficient_role 403 Insufficient role
read_only_key 403 Read-only API key
billing_account_required 403 Billing account required
project_not_ready 403 Project not ready
not_found 404 Not found
method_not_allowed 405 Method not allowed
not_acceptable 406 Not acceptable
conflict 409 Conflict
action_in_progress 409 Action in progress
already_enabled 409 Already enabled
not_eligible 409 Not eligible
insufficient_capacity 409 Insufficient capacity
snapshot_limit_reached 409 Snapshot limit reached
iso_limit_reached 409 ISO limit reached
iso_mounted 409 ISO mounted
name_taken 409 Name taken
group_in_use 409 Group in use
key_exists 409 Key exists
project_not_empty 409 Project not empty
project_deleting 409 Project being deleted
rule_exists 409 Rule exists
invitation_pending 409 Invitation pending
limit_reached 409 Limit reached
idempotency_key_reused 409 Idempotency key reused
unsupported_media_type 415 Unsupported media type
rate_limited 429 Rate limited
internal_error 500 Internal error
upstream_error 502 Upstream error
node_maintenance 503 Node maintenance
reverse_dns_unavailable 503 Reverse DNS unavailable
upstream_unavailable 503 Upstream unavailable

400 Bad Request

validation_error

400 Validation failed

When: The request body, a query parameter or the Idempotency-Key header is invalid, or the body is not valid JSON. errors lists each problem: the field (null when it is about the whole request), a code and a message.

What to do: Correct the fields that errors names and send the request again. Sending it unchanged gets the same answer.

Default detail: “One or more fields are invalid.”

feature_unavailable

400 Feature unavailable

When: The request uses a feature that is not available yet, such as user_data (cloud-init) on a reinstall or a new server.

What to do: Leave the field out.

Default detail: “This feature is not available yet.”

401 Unauthorized

authentication_required

401 Authentication required

When: The request carries no API key, or its Authorization header uses a scheme other than Bearer. The response has a WWW-Authenticate: Bearer header.

What to do: Send Authorization: Bearer <key>. See Authentication.

Default detail: “Authentication credentials were not provided.”

invalid_api_key

401 Invalid API key

When: The key is unknown, malformed or revoked, or the user it belongs to is deactivated. Changing or resetting your password revokes every key you have.

What to do: Create a new key on your profile page. After 20 failed attempts in 10 minutes, every key attempt from your address is refused with rate_limited until the 10 minutes are over.

Default detail: “The API key is unknown, revoked or malformed.”

api_key_expired

401 API key expired

When: The key is past the expiry date it was created with.

What to do: Create a new key on your profile page.

Default detail: “The API key has expired. Create a new one on your profile page.”

403 Forbidden

permission_denied

403 Permission denied

When: You are signed in, but not allowed to do this, and no more specific code applies.

What to do: Check that the key is yours and that you have the role the endpoint needs. Contact support if you think it is a mistake.

Default detail: “You do not have permission to perform this action.”

insufficient_role

403 Insufficient role

When: The endpoint needs the admin or owner role in the project and you are a member: ordering, upgrading, buying bandwidth, cancelling a server, and managing members and invitations. Deleting a project needs the owner.

What to do: Ask an admin or the owner of the project. See Projects and roles.

Default detail: “This action needs the owner or admin role in the project.”

read_only_key

403 Read-only API key

When: A read-only key sent a request that would change something. Read-only keys can only read and poll.

What to do: Use a key that is not read-only.

Default detail: “This API key is read-only, so it cannot make changes.”

billing_account_required

403 Billing account required

When: A billing account is missing. On a project's servers and other resources, the project's owner has none yet. On an invitation, you, the person inviting, have none.

What to do: Create the missing billing account in the console: the project owner for a project's resources, you for an invitation.

Default detail: “The project owner needs to create a billing account first.”

project_not_ready

403 Project not ready

When: The project is still being set up, so its servers and other resources can't be reached yet.

What to do: Wait a minute and try again. Contact support if it lasts.

Default detail: “The project is still being set up. Please try again shortly.”

404 Not Found

not_found

404 Not found

When: The resource does not exist, belongs to another project, or is in a project you are not a member of. A path the API does not have, a malformed id, and a page past the end of a list answer this too.

What to do: Check the project slug, the id and the path. A 404 never says whether the resource exists somewhere you can't see.

Default detail: “The resource does not exist, or you do not have access to it.”

405 Method Not Allowed

method_not_allowed

405 Method not allowed

When: The path exists, but not with this method.

What to do: Check the method on the endpoint's page, for example PATCH rather than PUT.

Default detail: “This method is not allowed on this resource.”

406 Not Acceptable

not_acceptable

406 Not acceptable

When: The request's Accept header rules out JSON, which is the only format the API answers with.

What to do: Send Accept: application/json, or no Accept header.

Default detail: “This API only answers with JSON.”

409 Conflict

conflict

409 Conflict

When: The resource is not in a state that allows the request, and no more specific code applies. For example, the server's host refused the operation, a cancellation of the other kind is already requested, or the same SSH key is being added by another request at that moment.

What to do: Read detail, check the resource's current state, and try again once it has changed.

Default detail: “The resource is not in a state that allows this request.”

action_in_progress

409 Action in progress

When: Another exclusive action is still running on the server, or its outcome is still being confirmed. action_id names it when it is in your project.

What to do: Poll that action until it finishes, then send your request again. See Actions.

Default detail: “Another action is still running on this server.”

already_enabled

409 Already enabled

When: IPv6 or the private network is already enabled on the server.

What to do: Nothing to do. The server's network shows the subnet or the private network.

Default detail: “This is already enabled.”

not_eligible

409 Not eligible

When: The server can't have this. The private network is not available for it, or it is a legacy server, which can't take snapshots.

What to do: Contact support if you need it.

Default detail: “This server is not eligible for this action.”

insufficient_capacity

409 Insufficient capacity

When: There is no capacity for this right now, for example no free IPv6 block for the server's location.

What to do: Try again later, or contact support.

Default detail: “There is not enough capacity for this right now.”

snapshot_limit_reached

409 Snapshot limit reached

When: Your account has as many snapshots as it is allowed.

What to do: Delete a snapshot you no longer need, then try again.

Default detail: “The account has reached its snapshot limit.”

iso_limit_reached

409 ISO limit reached

When: The project already has a custom ISO. A project can hold one.

What to do: Delete the project's custom ISO first.

Default detail: “The project already has a custom ISO.”

iso_mounted

409 ISO mounted

When: The ISO you are deleting is mounted on a server.

What to do: Unmount it from every server first.

Default detail: “The ISO is mounted on a server.”

name_taken

409 Name taken

When: Another firewall group in the project has this name, or another project has, or had, this slug. For a group, group_id names it when it can be read back.

What to do: Choose another name. If you were retrying a create whose answer you lost, the group with this name is the one you created: it is in group_id, or in the project's list of groups.

Default detail: “The name is already in use.”

group_in_use

409 Group in use

When: The firewall group you are deleting is still attached to servers. servers lists their ids.

What to do: Detach the group from those servers first. Deleting it would change what they allow.

Default detail: “The firewall group is still attached to servers.”

key_exists

409 Key exists

When: The public key is already in the project, whatever its comment. key_id names it.

What to do: Use the existing key. If you were retrying a create whose answer you lost, it is the one you added.

Default detail: “This public key is already in the project.”

project_not_empty

409 Project not empty

When: The project you are deleting still has servers, SSH keys, orders in progress or running actions.

What to do: Remove them, or wait for them to finish, then delete the project.

Default detail: “The project still has resources or orders in progress.”

project_deleting

409 Project being deleted

When: The project is being deleted, so it takes no new orders or actions.

What to do: Use another project.

Default detail: “The project is being deleted.”

rule_exists

409 Rule exists

When: The firewall group already has a rule that matches the same traffic, however it is spelled. rule_id names it when it can be read back.

What to do: Use the existing rule: it is in rule_id, or in the group's list of rules. If you were retrying a create whose answer you lost, it is the one you added.

Default detail: “An identical rule is already in the group.”

invitation_pending

409 Invitation pending

When: The email address already has an invitation to the project that is waiting to be accepted.

What to do: Resend that invitation instead of creating another.

Default detail: “There is already a pending invitation for this email address.”

limit_reached

409 Limit reached

When: You already have the most projects you can have.

What to do: Delete a project you no longer use, or contact support.

Default detail: “You have reached the maximum number of projects.”

idempotency_key_reused

409 Idempotency key reused

When: The Idempotency-Key was already used in this project for a request with another method, path or body.

What to do: Use a new key for every new request, and the same key only to repeat the same request.

Default detail: “This Idempotency-Key was already used for a different request.”

415 Unsupported Media Type

unsupported_media_type

415 Unsupported media type

When: The request body is not JSON.

What to do: Send the body as JSON with Content-Type: application/json.

Default detail: “Send the request body as application/json.”

429 Too Many Requests

rate_limited

429 Rate limited

When: The key, or your address, has used its budget for now. Retry-After says how many seconds to wait.

What to do: Wait for Retry-After, then continue at a slower pace. See Rate limits, which also covers the plain HTML 429 that can come before the API's own.

Default detail: “Too many requests. Wait for the time given in Retry-After.”

500 Internal Server Error

internal_error

500 Internal error

When: Something went wrong on our side.

What to do: Try again after a short wait. Repeat an action or an order with the same Idempotency-Key, so it can't happen twice. Before you repeat any other write, check whether it went through, unless its page says it is safe to send again. Contact support with the time and the path if it keeps happening.

Default detail: “Something went wrong on our side. Please try again.”

502 Bad Gateway

upstream_error

502 Upstream error

When: A system behind the API refused the request or did not answer. When an action or order was already recorded, the response carries its id in action_id or order_id, because the operation may have happened.

What to do: With action_id or order_id, poll that action or order instead of sending the request again. Otherwise try again after a short wait.

Default detail: “The request could not be completed. Please try again.”

503 Service Unavailable

node_maintenance

503 Node maintenance

When: The host the server runs on is in maintenance. Retry-After is 300 seconds.

What to do: Try again after Retry-After.

Default detail: “The server's host is in maintenance. Please try again later.”

reverse_dns_unavailable

503 Reverse DNS unavailable

When: The reverse DNS service is unavailable. Retry-After is 300 seconds.

What to do: Try again after Retry-After.

Default detail: “Reverse DNS is unavailable. Please try again later.”

upstream_unavailable

503 Upstream unavailable

When: A service behind the API, such as billing, is unavailable for now. Retry-After says when to try again.

What to do: Try again after Retry-After.

Default detail: “A service behind the API is unavailable right now.”

Action errors

An action that fails reports its own codes in error.code: failed, outcome_unknown, task_result_unavailable, timeout and resource_moved. See Actions.