Skip to main content

Handling errors

Every failure from publish, updatePoints, heartbeat, or get is a GoodchargeError, carrying a status, a code, details (an array of { path, message }), and a retryAfter. What you do about one depends less on the exact code than on which of these four situations it falls into.

Retried automatically

A 429 (too many requests), a 5xx, a timeout, or a network error are all retried for you, up to maxRetries (3 by default). goodcharge allows one request per second per key, so an occasional 429 under normal use is expected and handled without any code on your side.

Thrown synchronously, never as a rejected promise

An invalid_api_key or an invalid_option means something is wrong with how you built the GoodchargeStation or called startHeartbeat — a malformed key, or an out-of-range timeoutMs, maxRetries, or intervalMs. These are thrown synchronously, at the constructor or at startHeartbeat itself, before any request is made — never through a rejected promise. Neither call is asynchronous, so there is no promise for an await or a .catch() to intercept; a plain try/catch around the call itself is what catches these.

Needs a payload fix

An invalid_payload means the request reached goodcharge but the data itself failed validation. Its details array lists exactly what to fix, one { path, message } entry per problem — correct those fields and send the request again.

Needs a prior call

A not_published error means you called updatePoints or heartbeat before ever calling publish for this station. Call publish first; the other two calls depend on it.

Retry-After

When a 429 or 5xx response carries a Retry-After header, the SDK honours it — whether it is given in seconds or as an HTTP date — before its automatic retry. If that Retry-After is more than 60 seconds out, the SDK does not wait and retry on its own: it throws the error instead, still carrying retryAfter, so your code can decide whether and when to try again.

The full table of error codes, HTTP statuses, and what to do about each one lives in the SDK reference.