Skip to content

fix(core): surface missing deleted_at column in admin content list#1079

Open
eyupcanakman wants to merge 1 commit into
emdash-cms:mainfrom
eyupcanakman:fix/content-list-missing-deleted-at-column
Open

fix(core): surface missing deleted_at column in admin content list#1079
eyupcanakman wants to merge 1 commit into
emdash-cms:mainfrom
eyupcanakman:fix/content-list-missing-deleted-at-column

Conversation

@eyupcanakman
Copy link
Copy Markdown
Contributor

What does this PR do?

Fixes #709, where the admin content list silently breaks when a collection's backing ec_{collection} table is missing the deleted_at column.

ContentRepository.findMany always filters with WHERE deleted_at IS NULL. When the table was provisioned outside EmDash's migrations (for example a custom import script or schema drift on an old install) and has no deleted_at column, SQLite/D1 throws no such column: deleted_at. handleContentList only special-cased a missing table via isMissingTableError, so a missing column fell through to the generic CONTENT_LIST_ERROR ("Failed to list content"). An editor just sees published content go missing with nothing pointing at the cause.

The list handler now detects the missing deleted_at column and returns COLLECTION_SCHEMA_MISMATCH naming the collection, so the operator can tell the table does not match the expected schema. A new isMissingColumnError in utils/db-errors.ts mirrors the existing isMissingTableError. It takes an optional column argument, and the handler passes "deleted_at" so an unknown-column error from something else (such as ordering by a field a collection does not define) still returns the generic error rather than the wrong message.

The HTTP status stays 500. The issue's suggested fix asks for a 500 with a diagnostic message, and this path already returned 500, so only the error code is more specific now. I looked at 404 and 409 but kept 500 to match what the issue asked for. The public delivery path in loader.ts is left unchanged: it returns empty on a pre-migration database by design, and the issue notes the bot-facing surface is unaffected.

Closes #709

Type of change

  • Bug fix
  • Feature (requires maintainer-approved Discussion)
  • Refactor (no behavior change)
  • Translation
  • Documentation
  • Performance improvement
  • Tests
  • Chore (dependencies, CI, tooling)

Checklist

  • I have read CONTRIBUTING.md
  • pnpm typecheck passes
  • pnpm lint passes
  • pnpm test passes (or targeted tests for my change)
  • pnpm format has been run
  • I have added/updated tests for my changes (if applicable)
  • User-visible strings in the admin UI are wrapped for translation (if applicable). Not applicable here: this is an API error message, like the existing COLLECTION_NOT_FOUND.
  • I have added a changeset (if this PR changes a published package)
  • New features link to an approved Discussion: https://github.com/emdash-cms/emdash/discussions/...

AI-generated code disclosure

  • This PR includes AI-generated code — model/tool: Claude Opus 4.7

Screenshots / test output

Test Files  208 passed (208)
     Tests  3301 passed (3301)

New tests: tests/unit/utils/db-errors.test.ts covers isMissingColumnError (SQLite/D1, Postgres, case handling, non-Error inputs, the optional column argument). tests/unit/api/content-handlers.test.ts covers the missing-deleted_at table returning COLLECTION_SCHEMA_MISMATCH, and a healthy collection ordered by a field it does not define still getting the generic error.

Copilot AI review requested due to automatic review settings May 17, 2026 12:52
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 17, 2026

🦋 Changeset detected

Latest commit: 4394173

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 13 packages
Name Type
emdash Patch
@emdash-cms/cloudflare Patch
@emdash-cms/fixture-perf-site Patch
@emdash-cms/perf-demo-site Patch
@emdash-cms/cache-demo-site Patch
@emdash-cms/admin Patch
@emdash-cms/auth Patch
@emdash-cms/blocks Patch
@emdash-cms/gutenberg-to-portable-text Patch
@emdash-cms/x402 Patch
create-emdash Patch
@emdash-cms/auth-atproto Patch
@emdash-cms/plugin-embeds Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 17, 2026

Open in StackBlitz

@emdash-cms/admin

npm i https://pkg.pr.new/@emdash-cms/admin@1079

@emdash-cms/auth

npm i https://pkg.pr.new/@emdash-cms/auth@1079

@emdash-cms/blocks

npm i https://pkg.pr.new/@emdash-cms/blocks@1079

@emdash-cms/cloudflare

npm i https://pkg.pr.new/@emdash-cms/cloudflare@1079

emdash

npm i https://pkg.pr.new/emdash@1079

create-emdash

npm i https://pkg.pr.new/create-emdash@1079

@emdash-cms/gutenberg-to-portable-text

npm i https://pkg.pr.new/@emdash-cms/gutenberg-to-portable-text@1079

@emdash-cms/x402

npm i https://pkg.pr.new/@emdash-cms/x402@1079

@emdash-cms/plugin-ai-moderation

npm i https://pkg.pr.new/@emdash-cms/plugin-ai-moderation@1079

@emdash-cms/plugin-atproto

npm i https://pkg.pr.new/@emdash-cms/plugin-atproto@1079

@emdash-cms/plugin-audit-log

npm i https://pkg.pr.new/@emdash-cms/plugin-audit-log@1079

@emdash-cms/plugin-color

npm i https://pkg.pr.new/@emdash-cms/plugin-color@1079

@emdash-cms/plugin-embeds

npm i https://pkg.pr.new/@emdash-cms/plugin-embeds@1079

@emdash-cms/plugin-forms

npm i https://pkg.pr.new/@emdash-cms/plugin-forms@1079

@emdash-cms/plugin-webhook-notifier

npm i https://pkg.pr.new/@emdash-cms/plugin-webhook-notifier@1079

commit: 4394173

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves debuggability of admin content listing failures when an ec_{collection} table exists but is missing the deleted_at column expected by ContentRepository.findMany(). Instead of returning the generic CONTENT_LIST_ERROR, the API now surfaces a specific COLLECTION_SCHEMA_MISMATCH error so operators can identify schema drift / non-migrated tables.

Changes:

  • Add cross-dialect detection for “missing column” DB errors via isMissingColumnError(error, column?).
  • Update handleContentList to return COLLECTION_SCHEMA_MISMATCH when the missing column is specifically deleted_at.
  • Add unit tests covering the new DB error helper and the content list handler behavior; add a changeset and map the new error code to HTTP 500.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.

Show a summary per file
File Description
packages/core/src/utils/db-errors.ts Adds isMissingColumnError helper for SQLite/D1 and Postgres missing-column messages.
packages/core/src/api/handlers/content.ts Detects missing deleted_at column and returns COLLECTION_SCHEMA_MISMATCH instead of a generic list error.
packages/core/src/api/errors.ts Registers the new error code and maps it to HTTP 500.
packages/core/tests/unit/utils/db-errors.test.ts Adds test coverage for isMissingColumnError (dialects, case handling, column scoping, non-Error inputs).
packages/core/tests/unit/api/content-handlers.test.ts Adds regression tests for missing-deleted_at schema mismatch vs. unrelated unknown-column failures (e.g., orderBy).
.changeset/fix-content-list-missing-deleted-at-column.md Adds a patch changeset documenting the behavior change.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

handleContentList only special-cased a missing table, so a backing
ec_{collection} table without the deleted_at column threw "no such
column" and fell through to a generic CONTENT_LIST_ERROR, hiding
published content from editors with no diagnostic.

Detect the missing deleted_at column and return
COLLECTION_SCHEMA_MISMATCH naming the collection. isMissingColumnError
mirrors isMissingTableError and takes an optional column scope so an
unrelated unknown-column error still returns the generic error.

Closes emdash-cms#709
@eyupcanakman eyupcanakman force-pushed the fix/content-list-missing-deleted-at-column branch from 2c33c51 to 4394173 Compare May 19, 2026 11:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Admin UI silently buckets published content into Trash when ec_{collection} table schema lacks EmDash's expected columns

2 participants