Skip to content

Matches page titles and page text. Forty pages, indexed at build time.

Error messages

The errors you are most likely to see from a Balta service and from our API, what each one means, and the first thing to check.

Errors reach you from two places. PostgreSQL's own messages come from the database, through your driver. Errors from the dashboard and the API come from the control plane, each with a stable code.

Find the message below, read what it means, then do the first thing under it.

Connection errors

SSL error: certificate verify failed

Your client cannot verify the certificate your endpoint presented. There is no file to point it at: check that it is reading a trust store at all. libpq wants sslrootcert=system, which needs libpq 16 or newer. Java and Node do not read sslrootcert, and each needs a parameter of its own. See TLS and certificate verification.

FileNotFoundException: /home/you/.postgresql/root.crt

A Java stack trace through org.postgresql.ssl.LibPQFactory. pgjdbc's default SSL factory imitates libpq and looks for a root certificate file you never created. Add sslfactory=org.postgresql.ssl.DefaultJavaSSLFactory to the JDBC URL so the driver verifies against the JVM truststore instead.

invalid value for parameter "sslrootcert": "system"

The libpq behind your client is older than 16 and has no system keyword. Give it the path to the operating system's bundle instead: /etc/ssl/certs/ca-certificates.crt on Debian and Ubuntu, /etc/pki/tls/certs/ca-bundle.crt on RHEL and its family.

no pg_hba.conf entry for host

With no encryption at the end of the message, this is what a client that connects without TLS gets. It is a refusal, not a misconfiguration on our side. Set sslmode=verify-full.

connection refused

Nothing is listening at the address and port you used. The pooled and direct endpoints share a hostname and differ only by port, and the lower of your service's two ports is the pooled one. Check which one your configuration names, against the Connect tab — the pair is your service's own, so a port copied from another service's connection string reaches nothing.

server closed the connection unexpectedly

Check the service state in the dashboard. A restart looks exactly like this from a client that does not reconnect, and a plan change restarts the service.

So does a backend the kernel killed for taking the service past its memory ceiling. PostgreSQL then ends every other session with terminating connection because of crash of another server process and recovers before accepting new ones.

Capacity and limit errors

sorry, too many clients already

max_connections is reached. It is a hard ceiling set from your plan's memory, and plan limits lists it per plan. PostgreSQL holds superuser_reserved_connections slots back, three by default, so a role without superuser usually meets a message beginning remaining connection slots are reserved first.

Application traffic belongs on the pooled endpoint so that a few hundred clients do not need a few hundred backends. Then look for connections your application is not returning:

sql
SELECT usename, application_name, state, count(*)
FROM pg_stat_activity
GROUP BY usename, application_name, state
ORDER BY count(*) DESC;

could not fork new process for connection

Each service is capped at a number of processes derived from its plan, which for PostgreSQL means one per connection plus its background workers. The cap has headroom above max_connections, so this is not the message you get when you run out of connections. That one is sorry, too many clients already. If you see this, something in the service is forking beyond its backends.

could not extend file: No space left on device

The service's volume is full. Its size is the storage your plan allocates, and PostgreSQL reports this on the statement that needed the space.

Storage can be grown. It does not shrink: a request for less is refused with service.storage_below_current. See scaling. Measure with pg_database_size() to see this coming, and check pg_wal too, because a stalled archive accumulates WAL on local storage by design.

out of memory

An allocation PostgreSQL asked for was refused. The detail line names the size of the request and the memory context it was for. Check what the query was doing and whether a session-level work_mem was involved: work_mem is a default a session can raise, and one query can use it several times over, once for each sort or hash.

When the whole service goes past its memory ceiling, the kernel kills a process instead, and what you see is server closed the connection unexpectedly.

Permission errors

permission denied for schema

The role lacks USAGE on the schema, or lacks the object privilege. Check default privileges too: grants on existing tables do not cover tables created later. See privileges.

permission denied to create database

Your role does not have CREATEDB. Withholding it is what makes the database count a limit. See databases and roles.

permission denied to create extension

Read the hint. Must be superuser to create this extension means the extension is not trusted and is not one you can install; the eleven that are are on supported extensions. Must have CREATE privilege on current database is a different problem: the role is missing CREATE on the database or schema.

must be superuser to ...

The operation requires a privilege that is not granted on a managed service. Recent PostgreSQL versions often word this as permission denied, with a detail naming the SUPERUSER attribute. See the privilege model.

Errors from the dashboard and the API

Every error from the control plane has one shape. code is stable and meant for programs, message is written for people, and reference identifies this exact failure in our logs. detail, field, related_id and docs_url appear when there is something to say and are absent otherwise.

json
{
  "error": {
    "code": "service.database_limit_reached",
    "message": "This plan's database limit is reached.",
    "detail": "Databases are created through the platform, which is what makes the published number a limit rather than a guideline. Remove one, or change plan.",
    "field": "name",
    "reference": "err_EXAMPLE"
  }
}

The codes you are most likely to meet:

CodeStatusWhat it means
auth.unauthenticated401There is no valid session for this surface. Sign in again
auth.session_expired401The session reached its deadline. Sign in again
auth.mfa_required403Your organisation requires MFA and this session has not presented it
auth.step_up_required403This action needs you to confirm your password again
authz.capability_denied403You can see the resource, and your role lacks the capability detail names
not_found404It does not exist, or you cannot see it. The two are deliberately the same answer
validation_failed400A field is missing or has the wrong type or value. field names it where it can
rate_limited429Too many requests. Retry-After says how long to wait
resource.operation_in_progress409The service already has an operation running. related_id is that job
service.not_in_a_state_for_this_operation409The service's current state does not accept this operation
service.storage_below_current422Storage cannot be reduced
parameter.not_settable422The value comes from the plan and cannot be changed
billing.standing_denied403Not available while the organisation's billing is in its current state
internal_error500A fault on our side. Quote the reference
degraded503Something the request depends on is not answering. Try again shortly

Why 404 and not 403

A resource outside your scope answers not_found. A 403 would confirm that the resource exists, which is information you are not entitled to. authz.capability_denied is the different case: you can see the resource and your role lacks the capability.

Reporting one

If an error message from the platform is unclear, tell us through contact, and quote the reference if the error came from the API. An error that says what went wrong but not what to do next is a defect on our side.