Skip to content

Troubleshooting

Start with the failing request in your browser’s Network panel and the [caretcms] messages in your server logs. Preserve unsaved text before reloading, signing out, discarding drafts, or changing storage.

A production static build intentionally contains no admin or API routes. Author in astro dev, or use a separately deployed authoring server. delivery: 'auto' already detects Astro’s static output; delivery: 'static' makes that choice explicit. See Static delivery.

For server delivery, check your Astro host adapter and configured mountPath and apiBasePath (defaults /admin and /api/cms). enableAdmin: false hides the admin interface; it does not disable authenticated CMS API routes. Also check for your own routes overlapping the CMS paths.

  1. Confirm /api/cms/auth/session returns authenticated: true.
  2. Check that the page has a valid data-caret binding or supported data-caret-md prose. The signed-in empty-page hint means no editable fields were found.
  3. Switch from Preview to Edit and ensure enableInlineEditor is not false.
  4. Check /__caret/editor.js loads successfully and inspect console errors.

Bindings need a full collection::id::field or a field inside an ancestor data-caret-scope="collection::id". See Inline editing.

Response What to check
401 on save Session expired or missing; preserve local edits, then sign in again
403, missing request header Custom mutation clients need x-caret-request: 1
403, policy denial Your identity adapter’s authorize() decision for this action and collection
409 on password login An external identity provider is authoritative; use its login flow
Session rejected after login Stable CARET_SESSION_SECRET, matching across instances; cookie forwarding and HTTPS

Production password authentication requires configured credentials and a stable session secret; it fails closed when required secrets are missing. Check that variables are present, without printing secret values. The prefixed CARET_EDIT_PASSWORD takes precedence over legacy EDIT_PASSWORD. Check for accidental whitespace in your secret manager.

If your local .env password is ignored or the login page still says a temporary password is active, stop the dev server and run node --env-file=.env ./node_modules/astro/bin/astro.mjs dev. CaretCMS needs process/runtime environment variables; simply placing a file beside the project does not ensure that those variables are loaded into its server process.

See Authentication and Permissions.

First identify the status, rather than repeatedly saving:

  • Saved draft: Publish from the editor that owns the draft.
  • Published on a static site: Rebuild with access to the updated content, then deploy the resulting HTML and uploads.
  • Deploy requested: A successful webhook means accepted, not live. Check provider evidence or your deployment service.
  • Server delivery: Ensure the page is rendered on request and your cache has been invalidated. Policy-controlled edits remain drafts until publication.
  • Markdown body: Prose edits always need Publish, even on a server site.

A boolean publication field may also hide an entry from public Caret reads. See Saving and publishing and Deployment status.

If a static page in astro dev shows its template or published text after a reload, open the entry in Studio using the same signed-in session. Check the saved field value there before retyping or discarding anything. The on-page preview and persisted draft are separate checks.

Once Studio confirms the draft, Publish and rebuild. Verify the result with npm run preview, which serves the generated public HTML. If the draft itself is missing in Studio, investigate the save request, session, and storage path.

Error or symptom Recovery
Revision conflict (409) Preserve your edits, read the latest revision, compare, then reapply your intended change
stale_entry Published data changed since the draft started; preserve the draft before discarding and rebuilding it
stale_body Markdown source ranges changed; preserve edits, reload the current source, and reapply
legacy_draft An older structured draft lacks a tracked baseline; preserve it and recreate against current content
recovery_conflict Keep the recovery plan; an operator must reconcile storage before retrying
Rebuild failed or timed out Content may already be published; use Retry deploy or your deployment service

Do not interpret HTTP 200 from a bulk publish as every entry succeeding. Inspect published, conflicts, and failed. An interrupted entry may already have changed base content. See Publish recovery.

Check /api/cms/schema?collection=your-collection: source identifies the registered, dynamic, or inferred schema being used. Registered collection names must match exactly. An empty inferred collection has no useful shape; register an explicit schema or add representative data. Dynamic collections are created through the API, not a Studio schema-builder form.

For invalid stored data, repair the fields named in the validation issues. The live loader skips invalid entries when reading a collection and returns an error for an invalid single entry. Studio date formats use string inputs; there is no dedicated date picker. See Schemas.

Filesystem storage needs persistent content, metadata/history, draft overlays, and uploads. Keeping only .caret/data is insufficient. Use a persistent volume and backups, or a storage adapter designed for your host.

For concurrent Cloudflare writers, use the Durable Object adapter. KV’s eventual consistency does not solve concurrent-write conflicts. Filesystem and Markdown deployments must use one writer process.

  • Check the response’s validation error and supported image type/size.
  • For R2, configure publicBaseUrl or R2_PUBLIC_DOMAIN with an enabled public custom/r2.dev hostname. Test the returned URL while signed out.
  • For local uploads, ensure the uploaded files are persisted and included in static deployment artifacts.
  • Alt text is a separate Studio field; the inline image picker only changes the image URL.

Studio uses paginated requests (24 entries by default, maximum 100) and search. A storage adapter may still load its whole collection before those results are sliced. For larger data sets, measure adapter reads and consider a dedicated query layer.

Live collections read storage at render time. If you configure caching, bypass it for authenticated/private-preview responses and invalidate public pages after publication. Cache tags alone do not configure your CDN.

Include your package versions, host/delivery mode, a redacted config, reproduction steps, and the relevant response/error. Remove credentials, cookies, private content, and authorization headers before sharing at GitHub issues.