⚠️ Work in progress — createCMS is pre-1.0 and not production-ready (not tested in production). Expect breaking changes.
createCMS
Resources

Troubleshooting

Fixes for common problems with @createcms/core.

No cms.ts found

Cause. createcms generate could not locate your config. It searches cms.ts, src/cms.ts, and src/lib/cms.ts.

Fix. Pass the path explicitly:

npx createcms generate ./path/to/cms.ts

Schema changes are not applied

Cause. You added or changed a plugin that ships schema but did not regenerate and migrate. (Editing a collection never needs this: the schema is content-agnostic.)

Fix. Regenerate the schema, then apply it with Drizzle:

npx createcms generate
npx drizzle-kit generate && npx drizzle-kit migrate

The drizzle-kit commands need a drizzle.config.ts at your project root — see the Quickstart for the one to create.

To catch this in CI, run npx createcms generate --check — it fails when the committed schema is stale. See the CLI reference.

DATA_RETENTION_NOT_CONFIGURED

Cause. You called admin.runPruning without configuring retention.

Fix. Set dataRetention on createCMS:

createCMS({
  db,
  collections,
  media,
  authMiddleware,
  dataRetention: { keepDays: 30, keepMinCommits: 10 },
});

TENANT_SLUG_REQUIRED

Cause. The multi-tenant plugin is installed, but your authMiddleware did not return a tenantSlug.

Fix. Return it, typed as MultiTenantMiddlewareResult — see Multi-tenant → Installation.

AMBIGUOUS_SLUG

Cause. More than one root matches the slug you looked up.

Fix. Look up by rootId or full path instead of slug:

await cms.api.pages.getPublishedContent({ query: { rootId } });

PUBLISHED_CONTENT_NOT_FOUND

Cause. The entry has no published branch. getPublishedContent only returns published content.

Fix. Publish a branch first with publishBranch, or read the editing view with getBlockTree.

WebP optimization unavailable

Cause. The media optimize plugin tried to encode WebP in a browser without native support, and @jsquash/webp is not installed. Optimization is best-effort, so the original file still uploads; the failure surfaces as a string in useOptimize's state.error (there is no error code).

Fix. Install the optional @jsquash/webp fallback — see Media optimize → Installation.

On this page