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:
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.
{
"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:
| Code | Status | What it means |
|---|---|---|
auth.unauthenticated | 401 | There is no valid session for this surface. Sign in again |
auth.session_expired | 401 | The session reached its deadline. Sign in again |
auth.mfa_required | 403 | Your organisation requires MFA and this session has not presented it |
auth.step_up_required | 403 | This action needs you to confirm your password again |
authz.capability_denied | 403 | You can see the resource, and your role lacks the capability detail names |
not_found | 404 | It does not exist, or you cannot see it. The two are deliberately the same answer |
validation_failed | 400 | A field is missing or has the wrong type or value. field names it where it can |
rate_limited | 429 | Too many requests. Retry-After says how long to wait |
resource.operation_in_progress | 409 | The service already has an operation running. related_id is that job |
service.not_in_a_state_for_this_operation | 409 | The service's current state does not accept this operation |
service.storage_below_current | 422 | Storage cannot be reduced |
parameter.not_settable | 422 | The value comes from the plan and cannot be changed |
billing.standing_denied | 403 | Not available while the organisation's billing is in its current state |
internal_error | 500 | A fault on our side. Quote the reference |
degraded | 503 | Something 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.