Repository navigation
Releases: Classic298/prune-open-webui
Release list
v1.2.5
End Of Life
Important
The Prune Tool is now legacy and will not be maintained any further
The approach used by the prune tool here had some downsides with Kubernetes setups and was not very handy to use in day-to-day scenarios since it always required CLI access.
Successor:
The direct successor to this repository is the Prune Event Function found in my other repo here
It is easy to install, has a UI, is automated, and strictly better than the version in this repository.
Since maintaining both is not economical this repository is now LEGACY and will be archived (made read only) in the future.
You should no longer use this tool. As time passes, it will stop working with newer versions of Open WebUI.
If you ever encounter any bugs with this tool, they will NOT be fixed. Only the new Prune Event Function will receive support (as much as I can ofc).
Again thank you to everyone who helped test this, submitted PRs here and helped with the continuous improvement. The development is not dead, it just shifted to the other repo into a new event function.
So: Go to the other repo and download the Prune Event Function. It is the direct successor, already has more features, works better, better performance, many bug fixes this repository does not have and will never get that prevent wrongful deletions and much more.
Thanks for the journey and Enjoy the improved version on the Plugins Repo!
v1.2.4
[v1.2.4] - 2026-07-04
Compatible with Open WebUI v0.10.0
Caution
This release fixes three bugs that could destroy live user data (a storage-wipe path, shared
knowledge bases being gutted when their uploader's account was removed, and live KB search
embeddings being deleted on every real run) plus a bug that made age-based chat pruning
silently ineffective on SQLite, the default backend.
Upgrading is strongly recommended for all deployments. Update before your next run.
Important
⚠️ prune-open-webui will be slowly PHASED OUT in favor of an Event Function for native Open WebUI compatibility ⚠️
This allows for:
- a UI inside Open WebUI
- automatic deletions (e.g. if a chat gets deleted -> go check if any other chats can be deleted based on age fully automatically)
- easier setup
- more compatibility across deployment types (e.g. Kubernetes pods)
- less hassle when installing, as it is a plugin and doesn't require special setup
- decide between automatic deletions, on-demand deletions or both!
➡️ You will be able to find the Event Function here when it releases.
Added
--orphan-file-grace-hours N(default: 24,0disables): files younger than N hours are never
classified as orphaned. Uploading a file and referencing it (sending the message, adding it to a
knowledge base) are two separate requests in Open WebUI, so a prune running in that window could
previously delete an upload the user was still attaching. Applies to the standalone script, the
interactive CLI and the preview counts.
Changed
- Orphaned-file rule is now reference-based only. A file is deleted only when nothing references
it (no knowledge base, chat, folder, channel message or model). Previously a file was also deleted
whenever its uploader's account no longer existed, even if the file was still part of another
user's live knowledge base or chat: offboarding a user could silently gut shared knowledge bases.
Who uploaded a file no longer plays any role in whether its data is still needed. - Inactive-user pruning no longer deletes the user's files eagerly. The reference-based rule
applies instead: uploads backing another user's live knowledge base, chat or channel survive
account deletion, and the user's own unreferenced files are reclaimed by the orphan pass of the
same run. - Vector collections now follow file rows, exactly like storage bytes. Any file row that
survives the sweep (referenced, inside the grace window, or deferred to the next run) keeps its
embeddings. Previously a grace-protected upload kept its row and bytes but silently lost its
vectors in the same run, leaving a file that looks intact but returns nothing in retrieval. - Storage-orphan sweep preserves every existing file row. The upload cleanup now protects the
storage object of every file row in the database (unreferenced rows are removed by the database
pass first). Paths are matched raw, normalized, and by basename, so a non-canonicalUPLOAD_DIR
or a migrated data directory (pip to Docker, moved volume) can no longer cause every ref to
mismatch and classify all uploads as orphans. - Synchronous vector-store and storage calls inside async code paths (per-file collection drops,
bucket listing, physical deletion, preview counting) now run in worker threads, so the engine no
longer stalls the event loop when embedded in a server process.
Fixed
- A transient database error during the storage sweep could delete every upload. The active-path
lookup swallowed all exceptions and returned an empty preservation set, causing the sweep to treat
every object in local/S3/GCS/Azure storage as orphaned. It now aborts the pass instead. - SQLite: attachments of deleted chats were never reclaimed. Open WebUI does not enable SQLite
foreign-key enforcement, so deleting a chat leaves itschat_filerows behind, and the reference
scan trusted them: the attachments stayed pinned as "in use" forever, no matter how many sweeps
ran. Danglingchat_file/knowledge_file/channel_filerows are now cleaned before every sweep
and the reference scans verify the parent row still exists. - Knowledge-base embedding cleanup on file deletion never actually ran. It called a method that
exists on no cleaner class; the error was swallowed at debug level, so deleted files left their
chunks behind in every referencing knowledge-base collection. Deletion now goes through the
underlying vector client. - Completed the shared
knowledge-basescollection preservation fix (#37, #39) for the Milvus and
Qdrant multitenancy modes, which were still deleting the search-metadata embeddings of live
knowledge bases on every real run. - Pruned users left their login credentials in the database. Inactive-user deletion went through
a code path that removes the user row but not theauthrow, so the email and password hash of
every pruned account survived forever. Deletion now uses the same path as Open WebUI's own admin
delete, which removes both. - Legacy AI-generated images in live chats were deleted. Older chats reference generated images
only by URL (/api/v1/files/{id}/content) with no id field, which the reference scan could not
see. URL-style references are now recognized, and thechannel_filejunction is scanned too, so
channel uploads whose message has not been posted yet are no longer classified as orphans. - Preview counts now match execution exactly. Rows with a
NULLowner were deleted at execute
time but never counted in the preview; on large instances the per-table counts could exceed
SQLite's bind-parameter limit and silently report zero while execution deleted normally; and
messages inside channels deleted as orphaned in the same run were missing from the totals. All
counts now stream rows with the same filters execution uses, and the age-based and orphan chat
passes only count chats whose deletion actually succeeded. - Orphan sweeps silently under-deleted behind paginated API calls: only the 30 most recent knowledge
bases and 50 most recent notes were ever examined, and a single legacy prompt row (NULLtags)
aborted the entire run. These passes now stream raw rows. - Orphaned knowledge bases (owner deleted) are now de-referenced from every model's knowledge list,
as the age-based KB path already did, so shared models no longer point at a deleted collection.
The interactive CLI also gates the KB row deletion on the vector drop succeeding, matching the
other frontends. - GCS/Azure storage objects with nested names (containing
/) are skipped during orphan cleanup:
the deletion helper extracts keys naively and could have removed a different, live blob in a
shared bucket. - Standard-mode Milvus cleanup failed on a fresh process because the pymilvus
defaultconnection
alias was never established; it is now connected on demand. - The
--helpepilog advertised a--delete-orphaned-filesflag that does not exist.
v1.2.3
[v1.2.3] - 2026-07-03
Compatible with Open WebUI v0.10.0
Fixed
- Fixed #37 - Prune now preserves KB collection vectors
v1.2.2
[v1.2.2] - 2026-06-29
Compatible with Open WebUI v0.10.0
This release adds cleanup for channels and channel messages (requested in #34). Channels were previously left untouched; you can now keep busy Support/Alerts-style channels fast and tidy by expiring old messages, and reclaim channels left behind by deleted users.
Added
- Age-based channel-message pruning (
--channel-message-max-age-days N): delete messages older than N days from every channel while keeping the channel itself. Pinned messages are preserved unless--no-exempt-pinned-channel-messagesis passed. - Orphaned-channel cleanup (
--delete-orphaned-channels, default off): delete channels owned by a deleted user, along with their messages, reactions, members, file links, webhooks, and access grants. - Orphaned channel-message cleanup (
--delete-orphaned-channel-messages, default on): delete messages whose channel no longer exists. - Channel operations surfaced across all interfaces: interactive wizard ("Channel Message Age Pruning" menu plus orphaned-channel toggles), dry-run preview totals, and CSV export (
old_channel_message,orphaned_channel,orphaned_channel_messagecategories). - Added support for Open WebUI v0.10.0 which brings some schema changes across migrations.
v1.2.1.1
[v1.2.1.1] - 2026-06-02
Compatible with Open WebUI v0.9.6
Fixed
-
Active users' memories are no longer deleted during vector cleanup. On the non-multitenancy backends (Chroma, the default, plus PGVector, Milvus, and standalone Qdrant), the orphan sweep built its set of expected collections from active files and knowledge bases only. It never accounted for per-user
user-memory-{id}collections, so it treated every memory collection as orphaned and deleted it, including those of active users. A normal prune run could therefore wipe live memories.The cleaner now preserves
user-memory-{id}for every active user and removes only a deleted user's memory collection. This matches the multitenancy cleaners (Qdrant and Milvus multitenancy), which already scoped memory collections to active users and were not affected.
Who should upgrade
- Anyone on v1.2.1 using the Memories feature with Chroma, PGVector, Milvus, or standalone Qdrant should upgrade before their next run. Multitenancy deployments were unaffected.
v1.2.1
[v1.2.1] - 2026-06-02
Compatible with Open WebUI v0.9.6
⚠️ Breaking changes
- Pinned-chat exemption is now a separate flag. Previously
--exempt-chats-in-foldersalso preserved pinned chats. It now preserves foldered chats only, and pinned chats are kept by the new--exempt-pinned-chatsflag (off by default).- Impact: this changes behaviour silently for non-interactive runs (cron,
docker exec, systemd). If a command relied on--exempt-chats-in-foldersto keep pinned chats, add--exempt-pinned-chats, otherwise old pinned chats will be deleted on the next run. Interactive mode is unaffected in practice: it now asks about pinned and foldered chats as two separate prompts.
- Impact: this changes behaviour silently for non-interactive runs (cron,
Added
- Age-based knowledge base retention (destructive, opt-in). New
--delete-knowledge-bases-older-than-days N, with--knowledge-bases-age-field {created_at,updated_at}(defaultcreated_at). This deletes knowledge bases purely by age, even when the owner is active and the KB is in use. It mirrors Open WebUI's own KB deletion: it removes the KB's vector collection, deletes the KB record, removes the KB's search-metadata embedding, and de-references the KB from any model that points at it (so referencing models keep working). The KB's now-unreferenced files, uploads, and per-file vector collections are reclaimed by the orphan sweep. Interactive mode adds a dedicated Knowledge Base Retention (DANGEROUS) configuration section. - Orphaned KB metadata cleanup. New
--delete-orphaned-kb-metadata(default on,--no-to disable). Removes leftover entries in the sharedknowledge-basessearch collection whose knowledge base no longer exists (e.g. KBs deleted outside the tool or by an older version). The same removal is folded into both the age-based and orphaned KB deletion paths so no ghost is left behind. - Orphaned memories cleanup. New
--delete-orphaned-memories(default on,--no-to disable). Reconciles each active user'suser-memory-{id}collection against thememorytable and removes memories left in the vector store after a user deleted them, fixing leftover memories that keep getting injected into chat context via RAG. On Qdrant this relies on the companion Open WebUI fix that deletes memories by point id (see Compatibility); Chroma and PGVector were already correct. --exempt-pinned-chatsflag to preserve pinned chats during age-based deletion, wired through interactive config, the settings summary, preview counts, deletion, and CSV export.- New CSV export categories:
old_knowledge_base,orphaned_kb_metadata,orphaned_memory, so every new deletion type is visible in--export-previewbefore you execute.
Changed
- Documentation regrouped by deletion philosophy. Configuration Options is now split into three categories, ordered safest to most destructive: Orphaned Data Cleanup (owner no longer exists), Age-Based Deletion (bounded blast radius), and Retention Policy (deletes live, owned, in-use data), plus an Execution & Output group.
--run-vacuumnow reflects that it covers the main and vector databases. Help text, the interactive VACUUM warning, and the README warning were updated accordingly.count_old_chatsgained a defensiveexempt_pinned=Falsedefault so existing/external callers do not break.
Fixed
- VACUUM no longer runs unconditionally during routine prunes. The PGVector cleaner previously executed
VACUUM ANALYZE document_chunkon every--executerun as part of orphan-chunk cleanup, locking that table even when--run-vacuumwas not set. Vector-database VACUUM now happens only when--run-vacuumis enabled, where it already vacuums the whole vector database. Routine prunes are faster and no longer lock the table; reclaiming dead space is deferred to your maintenance window, as intended.
Compatibility
- The orphaned-memories cleanup on Qdrant requires the Open WebUI release that deletes memories by point id (Chroma and PGVector need no change). Other features work against current Open WebUI; see
COMPATIBILITY.md.
Upgrade notes
- Review the breaking change above and add
--exempt-pinned-chatsto any scripted command that was relying on--exempt-chats-in-foldersto keep pinned chats. - The new retention flag (
--delete-knowledge-bases-older-than-days) deletes live data and has no undo. Always run with--dry-run(optionally--export-preview) first.
v1.2.0
v1.2.0
Compatible with Open WebUI v0.9.0
Added
- Full rewrite to async
- Performance improvements
- S3 cleanup added
- Cleanup for orphaned automations
- Cleanup for orphaned automation runs
v1.1.0
v1.1.0
Compatible with Open WebUI v0.8.0+
Added
- Input validation for the stream_rows helper to fail fast on misuse (empty columns, invalid batch size)
- Backwards-compatible knowledge_bases parameter on get_active_file_ids to prevent breakage when merging with other branches
Fixed
- Resolved Out-of-Memory crashes on large PostgreSQL databases by replacing full ORM object loading with memory-safe batched SQL streaming throughout all scan and deletion paths
- Fixed silent data-loss risk where files and records could be incorrectly classified as orphaned on PostgreSQL due to UUID vs string type mismatches in set membership checks
- Fixed missing-table detection on PostgreSQL — the tool now correctly handles both SQLite and PostgreSQL error formats when scanning optional tables (knowledge_file, chat_file, chat_message)
- Fixed a bug where the error pattern matcher could suppress real database errors (e.g. "operator does not exist") by falsely treating them as missing-table conditions
- Fixed stale user snapshot in Stage 4 cleanup — user IDs are now recomputed after deletions to prevent over- or under-deletion when the application is live during pruning
- Fixed potential infinite hangs on SQLite by adding retry-with-backoff to all database scan operations, matching the existing retry behavior for chat scanning
- Fixed a bug where missing ORM attributes on older Open WebUI versions (e.g. Folder.items, Model.params) could silently produce incomplete preservation sets, leading to accidental file deletion
Changed
- Knowledge base scanning now uses lightweight SQL queries instead of the ORM API, avoiding eager-loading of file relationships that caused memory spikes on databases with large knowledge bases
- All ID comparisons across the codebase are now consistently normalized to strings at every boundary, ensuring correct behavior on both SQLite (string IDs) and PostgreSQL (UUID IDs)
- Orphaned file counting in preview mode now uses streaming with Python-side filtering instead of SQL IN clauses, eliminating SQLite's ~999 parameter limit and PostgreSQL memory pressure on large datasets
- Version-sensitive ORM attributes are now checked with hasattr before query construction instead of catching errors after the fact, allowing real bugs to surface immediately
v1.0.7
v1.0.7
Compatible with Open WebUI v0.8.0+
Fixed
- Fix PGVector cleanup for deployments where the pgvector database is on a separate PostgreSQL server and not a unified database
v1.0.6
v1.0.6
Compatible with Open WebUI v0.8.0+
Added
- Added --no- flag variants for all default-True orphaned data deletion options (--no-delete-orphaned-prompts, --no-delete-orphaned-knowledge-bases, --no-delete-orphaned-models, --no-delete-orphaned-notes, --no-delete-orphaned-folders), enabling selective category-by-category cleanup (#15)