Skip to content

v1.2.4

Choose a tag to compare

@Classic298 Classic298 released this 03 Jul 22:39
· 1 commit to main since this release
3140e4d

[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:

  1. a UI inside Open WebUI
  2. automatic deletions (e.g. if a chat gets deleted -> go check if any other chats can be deleted based on age fully automatically)
  3. easier setup
  4. more compatibility across deployment types (e.g. Kubernetes pods)
  5. less hassle when installing, as it is a plugin and doesn't require special setup
  6. 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, 0 disables): 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-canonical UPLOAD_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 its chat_file rows behind, and the reference
    scan trusted them: the attachments stayed pinned as "in use" forever, no matter how many sweeps
    ran. Dangling chat_file/knowledge_file/channel_file rows 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-bases collection 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 the auth row, 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 the channel_file junction 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 NULL owner 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 (NULL tags)
    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 default connection
    alias was never established; it is now connected on demand.
  • The --help epilog advertised a --delete-orphaned-files flag that does not exist.