Skip to content

fix(api): make single-entity delete resilient to file-cleanup failures (#1033)#1038

Closed
sanjibani wants to merge 1 commit into
basicmachines-co:mainfrom
sanjibani:fix/delete-entity-file-cleanup
Closed

fix(api): make single-entity delete resilient to file-cleanup failures (#1033)#1038
sanjibani wants to merge 1 commit into
basicmachines-co:mainfrom
sanjibani:fix/delete-entity-file-cleanup

Conversation

@sanjibani

Copy link
Copy Markdown

Closes #1033.

The `DELETE /v2/projects//knowledge/entities/` endpoint returns 500 for non-markdown entities when the file cleanup step cannot resolve the file path (cloud storage target mismatch, missing local mirror, or already-deleted after a concurrent delete-directory pass). The DB delete is what callers actually need, so wrap `file_service.delete_entity_file` in try/except and log a warning instead of propagating. Mirrors how `delete_directory` catches per-entity errors.

In the reported bulk removal of 910 entities, all 339 non-.md entities failed with 500 even though `POST .../knowledge/delete-directory` (which shares the same `delete_entity` code path) cleared them with zero failures. That asymmetry is the surface symptom; the underlying fix is to make the single-entity path just as forgiving as the directory path.

Regression test `test_delete_entity_succeeds_when_file_cleanup_raises` asserts `delete_entity` still returns `True` and the DB row is gone when the file service raises. Verified locally: passes with the fix, fails without it.

Closes basicmachines-co#1033. The DELETE /v2/projects/<id>/knowledge/entities/<uuid>
endpoint returns 500 for non-markdown entities when the file cleanup
step cannot resolve the file path (cloud storage target mismatch,
missing local mirror, or already-deleted after a concurrent
delete-directory pass). The DB delete is what callers actually need,
so wrap file_service.delete_entity_file in try/except and log a
warning instead of propagating the exception. Mirrors how
delete_directory catches per-entity errors.
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b6f2488b88

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

# of delete_directory, which catches per-entity errors instead of failing the batch.
try:
await self.file_service.delete_entity_file(entity)
except Exception:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve failed file deletes in directory results

When delete_directory calls delete_entity, any real local filesystem failure from delete_entity_file (for example PermissionError on a read-only project or invalid file path state) is now swallowed here, so delete_directory increments successful_deletes and downstream MCP JSON reports deleted: true because failed_deletes == 0, even though the file was not removed. Since files are the source of truth and the next sync treats a remaining file with no DB row as new, narrow this suppression to the missing/remote cleanup cases or return a status that lets directory deletes report the per-file failure.

Useful? React with 👍 / 👎.

@sanjibani

Copy link
Copy Markdown
Author

recheck

@phernandez phernandez added cla needed The contributor needs to sign the CLA dco needed The contributor needs to submit a DCO labels Jul 15, 2026 — with ChatGPT Codex Connector

Copy link
Copy Markdown
Member

Thanks for the contribution. Two contributor gates are still blocking this PR:

Once both checks are green, maintainers can take over any remaining implementation changes needed to get this merged.

@phernandez

Copy link
Copy Markdown
Member

Thank you for investigating #1033 and proposing a defensive cleanup path. We verified the current single-entity delete implementation against the real non-Markdown file path and have now merged #1056, which asserts that the file, database row, and search entry are all removed. The broader catch-and-continue behavior in this PR could delete database state after an unexpected file-cleanup failure, leaving the source file available to be re-indexed later, so we do not want to take that implementation. Since the reported path is now covered by a regression test, I am closing this PR as superseded. We appreciate the contribution.

@phernandez phernandez closed this Jul 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla needed The contributor needs to sign the CLA dco needed The contributor needs to submit a DCO

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] DELETE /knowledge/entities/{id} returns 500 for non-markdown (file-type) entities

3 participants