strapi/strapi · error

Cannot delete a draft document

Error message

Cannot delete a draft document

What it means

deleteDocument removes an entire document (all locales and the published+draft pair). It refuses to delete only the draft version, because that would orphan the published entry and break draftAndPublish integrity. When the content type has draftAndPublish enabled and params.status === 'draft', the call is rejected. To discard draft edits, use the discard-draft operation instead.

Source

Thrown at packages/core/core/src/services/document-service/repository.ts:389

    const lookupQuery = await async.pipe(
      validateParams,
      omit('status'),
      i18n.defaultLocale(contentType),
      i18n.multiLocaleToLookup(contentType),
      transformParamsToQuery(uid),
      (query) => assoc('where', { ...query.where, documentId }, query)
    )(params);

    const selectionQuery = await async.pipe(
      validateParams,
      omit('status'),
      pickSelectionParams,
      transformParamsToQuery(uid)
    )(params);

    if (hasDraftAndPublish && params.status === 'draft') {
      throw new Error('Cannot delete a draft document');
    }

    const entriesToDelete = await strapi.db.query(uid).findMany(lookupQuery);

    const deletedEntries = await async.map(entriesToDelete, (entryToDelete: any) =>
      entries.delete(entryToDelete.id, selectionQuery)
    );

    entriesToDelete.forEach(emitEvent('entry.delete'));

    return { documentId, entries: deletedEntries };
  }

  async function create(opts = {} as any) {
    const { documentId: _documentId, ...params } = opts;

    const queryParams = await async.pipe(
      validateParams,

View on GitHub (pinned to 4a4101264d)

Solutions

  1. Delete the whole document: strapi.documents(uid).delete({ documentId }) (omit status).
  2. To remove only the published version, use status: 'published'.
  3. To discard draft changes, use the discard-draft action (strapi.documents(uid).discardDraft(...)) or unpublish as appropriate.
  4. Never pass status: 'draft' to deleteDocument on draftAndPublish content types.

Example fix

// before (throws)
await strapi.documents('api::article.article').delete({
  documentId,
  status: 'draft',
});

// after — delete the whole document
await strapi.documents('api::article.article').delete({ documentId });

// or discard only the draft changes
await strapi.documents('api::article.article').discardDraft({ documentId });
Defensive patterns

Strategy: validation

Validate before calling

function deleteDocumentSafe(uid, opts) {
  const ct = strapi.contentType(uid);
  const hasDP = ct.options?.draftAndPublish === true;
  if (hasDP && opts.status === 'draft') {
    throw new Error('Use discardDraft to remove draft changes, or omit status to delete the document.');
  }
  return strapi.documents(uid).delete(opts);
}

Type guard

const isDraftDeleteAttempt = (ct, opts) =>
  ct.options?.draftAndPublish === true && opts?.status === 'draft';

Prevention

When it happens

Trigger: Calling strapi.documents('api::article.article').delete({ documentId, status: 'draft' }) on a content type with draftAndPublish enabled.

Common situations: Confusing delete with unpublish/discard-draft; a UI button wired to delete the draft; automation that loops over statuses to delete selectively.

Related errors


AI-assisted analysis of strapi/strapi@4a4101264d (2026-08-12). Data as JSON: /api/errors/6aafa3b374187dad. Report an issue: GitHub.