Error handling
Every failure in @ghostwritr/next throws a single typed error, GhostwritrError. It carries a status (HTTP status, or 0 for client-side/config/network failures), a stable code, the message, and optional details. Reads fail closed: there’s no silent empty result — a missing feed throws.
For the cross-SDK error model, see Error handling.
Catch and branch on code
Section titled “Catch and branch on code”Import GhostwritrError from the root @ghostwritr/next (it’s client-safe — types and the error class only):
import { GhostwritrError } from "@ghostwritr/next";import { gw } from "@/lib/ghostwritr";
try { const articles = await gw.getArticles(); // ...render} catch (e) { if (e instanceof GhostwritrError) { if (e.code === "NOT_FOUND") { // No published feed for this siteId yet, or the siteId is wrong. } else { // Transient: RATE_LIMITED, SERVER_ERROR, NETWORK_ERROR, INVALID_RESPONSE. } } throw e;}The codes
Section titled “The codes”code | status | What it means | What to do |
|---|---|---|---|
NOT_FOUND | 404 | No published feed exists for this siteId — an unseeded site, or a wrong/typo’d siteId. | Check your siteId. Until you publish your first article, expect this. |
RATE_LIMITED | 429 | Too many requests to the feed origin. | Back off and retry; widen your revalidate window to fetch less often. |
SERVER_ERROR | 5xx | The feed origin returned a server error. | Transient — retry, or serve a cached/last-known state. |
NETWORK_ERROR | 0 | The fetch itself failed (DNS, TLS, connection). | Transient — retry. Check connectivity from your runtime. |
INVALID_RESPONSE | varies | The feed returned non-JSON, or a malformed manifest/page/article (a contract violation). | Not your fault to fix at runtime — log details and report it. |
CONFIG | 0 | Bad config caught at client creation — missing siteId, or invalid revalidate/tags. | Fix the createGhostwritr / createRevalidateHandler call. |
Distinguishing unseeded from broken
Section titled “Distinguishing unseeded from broken”NOT_FOUND is the expected state before you publish your first article — the feed doesn’t exist until the engine builds it. Treat it differently from the transient codes: a NOT_FOUND won’t fix itself by retrying, but a RATE_LIMITED, SERVER_ERROR, or NETWORK_ERROR will.
const TRANSIENT = new Set(["RATE_LIMITED", "SERVER_ERROR", "NETWORK_ERROR"]);
try { return await gw.getArticles();} catch (e) { if (e instanceof GhostwritrError && TRANSIENT.has(e.code ?? "")) { return []; // degrade gracefully; the page renders without the list } throw e; // NOT_FOUND / INVALID_RESPONSE / CONFIG are real bugs — surface them}What to reach for next
Section titled “What to reach for next”- Error handling (concept) — the shared
GhostwritrErrormodel across SDKs. - Keyless reads — why reads fail closed.
- API reference —
GhostwritrErrorandGhostwritrErrorCode.