Skip to content
Last updated

Errors

The Platform, Management and VKS HTTP APIs use Problem Details (application/problem+json). Check the status and machine-readable code together with the operation you called. Codes are open strings, not an exhaustive enum; keep a fallback for unfamiliar values. Human-readable title and detail are not branching keys.

Problem Details · problem+json Check code Schema-specific fields RPC: protocol errors

The error body

FieldRequiredMeaning
typeyesURI identifying the problem category
titleyesHuman-readable label
statusyesHTTP status
codeyesMachine-readable service code; sometimes unspecified
detailnoExplanation for this occurrence
instancenoOccurrence identifier; include it in support requests
{
  "type": "https://docs.vilna.io/apis/errors#not-found",
  "title": "Not Found",
  "status": 404,
  "code": "address.not_found",
  "detail": "address not found",
  "instance": "/traces/0123456789abcdef0123456789abcdef"
}

Use the schema declared by the operation for fields such as fields, max or window_seconds.

Status codes

400

Invalid Request

Fix malformed input. Platform and Management may use different codes for the same status.

{
  "type": "https://docs.vilna.io/apis/errors#invalid-request",
  "title": "Invalid Request",
  "status": 400,
  "code": "request.malformed",
  "detail": "The request could not be decoded.",
  "instance": "/traces/0123456789abcdef0123456789abcdef"
}
401

Unauthorized

Check the credential and its service.

{
  "type": "https://docs.vilna.io/apis/errors#unauthorized",
  "title": "Unauthorized",
  "status": 401,
  "code": "unspecified",
  "detail": "You are not authorized to access this resource. If the problem persists, please contact our support team.",
  "instance": "/unauthorized?method=createInvoice"
}
403

Forbidden

The caller lacks access. Check current permissions; an idempotency key grants no access.

404

Not Found

The resource is absent or not visible to this caller.

{
  "type": "https://docs.vilna.io/apis/errors#not-found",
  "title": "Not Found",
  "status": 404,
  "code": "project.not_found",
  "detail": "project not found",
  "instance": "/traces/0199ce911a2b7c019c2a9d0010eaa310"
}
405

Method Not Allowed

Use a method supported by the route.

408

Request Canceled

A canceled connection does not prove that a mutation failed. Retry with its original intent key and inputs when required.

409

Conflict

The operation conflicts with resource state or its idempotency binding. Inspect code before deciding what to do.

{
  "type": "https://docs.vilna.io/apis/errors#conflict",
  "title": "Conflict",
  "status": 409,
  "code": "invoice.address_occupied",
  "detail": "address already has an active invoice with different parameters",
  "instance": "/traces/0123456789abcdef0123456789abcdef"
}
413

Request Too Large

Reduce the payload to the endpoint’s size limit.

422

Precondition Failed

A business rule or state precondition rejected the request. Fix that condition before retrying.

{
  "type": "https://docs.vilna.io/apis/errors#precondition",
  "title": "Precondition Failed",
  "status": 422,
  "code": "invoice.not_cancellable",
  "detail": "invoice cannot be cancelled in current status",
  "instance": "/traces/0123456789abcdef0123456789abcdef",
  "fields": [
    {
      "name": "status",
      "reason": "confirmed"
    }
  ]
}
429

Too Many Requests

This can mean a resource quota, an action window or a resend cooldown. See Rate limits for the different recovery paths.

501

Not Implemented

The operation is unsupported. Repeating unchanged input will not add support.

502

Bad Gateway

A required service was unavailable. Retry with backoff and the same mutation intent.

503

Service Unavailable

The operation is temporarily unavailable. Retry with backoff, preserving the mutation key and inputs.

{
  "type": "https://docs.vilna.io/apis/errors#service-unavailable",
  "title": "Service Unavailable",
  "status": 503,
  "code": "service.temporarily_unavailable",
  "detail": "The operation is temporarily unavailable. Please try again later."
}
504

Gateway Timeout

The request exceeded its deadline. The outcome may be uncertain; preserve the original intent on retry.

5xx

Server Error

An unexpected server error does not establish whether a side effect occurred. Use backoff and the original mutation key; reconcile if its replay is unavailable.

Idempotency conflicts

The conflicts idempotency_in_progress, idempotency_request_mismatch, idempotency_result_expired and idempotency_result_unavailable require different recovery steps. Keep the original key and request inputs; never automatically substitute a new key for an unknown outcome. See Idempotency for scope, windows and per-service recovery. An invalid or repeated header returns 400, rather than an idempotency 409.

Validation fields

400 and 422 schemas can include fields, an array of { "name": "…", "reason": "…" } entries. Entries can describe invalid input or diagnostic state, such as name: status, reason: confirmed when an invoice cannot be cancelled. A malformed JSON request need not identify a single field.

Rate limits and quotas

Resource capacity

A QuotaExceededProblem adds max, the effective configured resource limit in the operation’s scope. It is not usage or remaining capacity. Waiting does not free capacity: reduce usage where the product permits it, or arrange a limit change. A zero limit prohibits new admissions without disabling resources already held.

{
  "type": "https://docs.vilna.io/apis/errors#too-many-requests",
  "title": "Too Many Requests",
  "status": 429,
  "code": "address.quota_exceeded",
  "detail": "the project has reached its address limit",
  "max": 100
}
{
  "type": "https://docs.vilna.io/apis/errors#too-many-requests",
  "title": "Too Many Requests",
  "status": 429,
  "code": "project.limit_exceeded",
  "detail": "project limit exceeded",
  "max": 2
}

Time windows

For balance refresh, RateLimitExceededProblem adds max and window_seconds. The window duration is not the remaining wait. Retry-After gives whole seconds until an earliest retry when max > 0 and the deadline is known; it is omitted for max: 0 or an unknown deadline. A zero limit requires a policy change, not backoff alone. The next attempt checks capacity again.

{
  "type": "https://docs.vilna.io/apis/errors#too-many-requests",
  "title": "Too Many Requests",
  "status": 429,
  "code": "balance.refresh_rate_exceeded",
  "detail": "the project has reached its balance refresh rate limit",
  "max": 1,
  "window_seconds": 60
}

Manual resend cooldown

Notification resend can return 429 with notification.resend_delayed. Its Retry-After is the rounded-up wait to the later of the delivery pause and the cooldown since the last attempt. It is a hint, not a reservation. Retry the same request and intent key after waiting. A queued/running send is instead 409 notification.send_in_progress; expired content is 409 notification.payload_unavailable. Inspect the notification and its logs before another action.

{
  "type": "https://docs.vilna.io/apis/errors#too-many-requests",
  "title": "Too Many Requests",
  "status": 429,
  "code": "notification.resend_delayed",
  "detail": "notification resend is delayed",
  "instance": "/traces/0123456789abcdef0123456789abcdef"
}

VKS problem types

These type fragments are used by public VKS response examples. They are examples of open codes, not the complete set of possible responses. Preserve the supplied type URI when logging an error.

backend.failure

Unexpected failure; retry the original intent with backoff, then reconcile if the outcome remains uncertain.

{
  "type": "https://docs.vilna.io/apis/errors#backend.failure",
  "title": "Internal Server Error",
  "status": 500,
  "code": "backend.failure",
  "detail": "internal error"
}

request.invalid

Correct the request against the operation schema.

{
  "type": "https://docs.vilna.io/apis/errors#request.invalid",
  "title": "Bad Request",
  "status": 400,
  "code": "request.invalid",
  "detail": "invalid request"
}

transaction.not_found

Check the transaction identity and workspace access.

{
  "type": "https://docs.vilna.io/apis/errors#transaction.not_found",
  "title": "Not Found",
  "status": 404,
  "code": "transaction.not_found",
  "detail": "transaction not found"
}

account.state_invalid

Read the account state and check which states the operation permits. Wait only if setup is still progressing; some operations remain unavailable for an active account.

{
  "type": "https://docs.vilna.io/apis/errors#account.state_invalid",
  "title": "Conflict",
  "status": 409,
  "code": "account.state_invalid",
  "detail": "account state does not allow this operation"
}

transaction.state_invalid

Read the transaction state before choosing another action.

{
  "type": "https://docs.vilna.io/apis/errors#transaction.state_invalid",
  "title": "Conflict",
  "status": 409,
  "code": "transaction.state_invalid",
  "detail": "transaction state does not allow this operation"
}

transaction.send_in_progress

A send is already pending. Check send history rather than queueing another send.

{
  "type": "https://docs.vilna.io/apis/errors#transaction.send_in_progress",
  "title": "Conflict",
  "status": 409,
  "code": "transaction.send_in_progress",
  "detail": "transaction has a pending send attempt"
}

transaction.already_sent

The node already accepted the transaction. Check send history; this does not establish chain confirmation.

{
  "type": "https://docs.vilna.io/apis/errors#transaction.already_sent",
  "title": "Conflict",
  "status": 409,
  "code": "transaction.already_sent",
  "detail": "transaction was already accepted by RPC"
}

transaction.send_limit_exceeded

max is the transaction’s shared manual and automatic attempt limit. Waiting alone does not reset it.

{
  "type": "https://docs.vilna.io/apis/errors#transaction.send_limit_exceeded",
  "title": "Too Many Requests",
  "status": 429,
  "code": "transaction.send_limit_exceeded",
  "detail": "transaction send limit exceeded",
  "max": 10
}

signer.limit_exceeded

max is the workspace limit for registered signers plus unexpired invitations. Offline signers still count. Remove unused invitations or signers that are eligible for deletion, or contact support@vilna.io about the limit.

{
  "type": "https://docs.vilna.io/apis/errors#signer.limit_exceeded",
  "title": "Too Many Requests",
  "status": 429,
  "code": "signer.limit_exceeded",
  "detail": "workspace signer limit exceeded",
  "max": 10
}

transaction.send_unsupported

The result is not a broadcastable transaction; an ingredient cannot be sent through this action.

{
  "type": "https://docs.vilna.io/apis/errors#transaction.send_unsupported",
  "title": "Unprocessable Entity",
  "status": 422,
  "code": "transaction.send_unsupported",
  "detail": "signed result is not a broadcastable transaction"
}

transaction.rpc_not_configured

VKS cannot submit transactions to this network because no node is configured for it. Contact support@vilna.io about network availability before retrying.

{
  "type": "https://docs.vilna.io/apis/errors#transaction.rpc_not_configured",
  "title": "Unprocessable Entity",
  "status": 422,
  "code": "transaction.rpc_not_configured",
  "detail": "RPC is not configured for this network"
}

Errors across services

Platform, Management and VKS use the HTTP problem envelope above, with service-specific codes and extensions. Blockchain RPC has its own protocol errors; see JSON-RPC error handling.

Blockchain RPC

A rate-limited JSON-RPC call returns the following protocol error; gRPC returns HTTP 429 with an empty body.

{
  "jsonrpc": "2.0",
  "error": {
    "code": -32005,
    "message": "rate limit exceeded",
    "data": {
      "source": "vilna"
    }
  },
  "id": null
}

There are no X-RateLimit-* headers. Use the response-specific Retry-After rules above; do not treat every 429 as a temporary window. For retryable network and server failures, use backoff and preserve mutation intent.