Release Date: September 2026
Overview
Diskover 2.6.1 is a maintenance release following the core release of v2.6.0. It concentrates on the correctness and reliability of what 2.6.0 introduced, in five key areas:
Reporting accuracy. Size and cost totals that combined files and directories were counting the same bytes multiple times. Directory rollups are now reported separately from file totals everywhere they are summed.
Index selection integrity. Several independent defects could cause an entire top path — or an entire index — to disappear silently from search scope, dashboards, and reports. All of them are now resolved against the actual index metadata rather than inferred from index names.
Task scheduling and concurrency. Scheduled crawls that were missed because no worker was free are no longer dropped, the task start lock is now enforced by the database, and Reset Status and Run Now refuse to act on a task that is provably running.
LDAP authentication and authorization. Four separate defects are fixed. Two of these were found to unintentionally deny access outright and were prone to surface on upgrade from 2.4.x and older versions of Diskover.
Security hardening. Task Panel actions now require POST with a CSRF token, further aligning to higher security standards.
Reporting & Data Accuracy
Diskover directory documents carry a recursive rolled-up size — the sum of every file beneath them. Any total that summed file and directory documents together therefore counted each byte once for the file and again for every matching parent directory. The overstatement grew with directory depth, and was silent: the numbers looked plausible. Four surfaces were affected, and all four now feed only file bytes into anything additive, reporting directory rollups separately as an explicitly non-additive figure.
[DEV-1010]
The Metrics API (/api.php/{index}/metrics) returned overall_stats.total_size and average_size several times larger than actual used capacity, and those figures didn’t match the Diskover Web analytics pages for the same index. Size statistics are now computed over file documents only. A new directory_stats block reports directory average, minimum, maximum, and count — deliberately without a total, since summing rollups is not a meaningful quantity. This endpoint also backs the AI Data Assistant's file-metrics tool, so MCP assistant answers are corrected by the same change.
[DEV-1227]
The tag size API (/api.php/{index}/tagsize) inflated the size of any tag applied to a directory and to content beneath it by up to several hundred times on a tag applied near the top of a deep tree. This endpoint was automatically opting in by default, and resulted in standard user actions creating overlapping conditions. The type parameter now resolves to exactly one document type; the default is file.
[DEV-1228]
On the Tags page, the "Show all" toggle inflated the per-tag Size column, the Total row, the percentages, the size chart, and the CSV export. File bytes now drive all of those, and directory rollups appear in a new Dir size (rollup) column.
[DEV-1157]
Cost Analysis had the same defect on the same toggle, affecting the Cost and Size columns, both totals, the percentages, and both charts. File bytes now drive all additive figures, with new Dir cost (rollup) and Dir size (rollup) columns alongside. The default files-only view was always correct, and the shipped stock Cost Analysis queries are extension-scoped — directories carry no extension — so out-of-the-box configurations were not affected.
Two further defects in this area were not double-counting but truncation. A ceiling of 10,000 aggregation buckets was hard-coded in two places on the assumption that Elasticsearch imposed it; Elasticsearch's actual limit for aggregation buckets is search.max_buckets, which defaults to 65,536. Sites with more than 10,000 unique owners or groups were silently losing rows.
[DEV-1347]
The Top Users and Top Groups tables on the User Analysis page stopped at exactly 10,000 entries regardless of how many owners or groups existed in the selected indices, and the CSV export and pagination inherited the same cap. Everything beyond 10,000 was dropped with no warning, and the percentages were computed against the truncated set. On the reference index — 11,990 unique owners — roughly 2,000 owners and 2,000 groups were missing. The aggregation now requests up to 65,536 buckets.
[DEV-1348]
The Metrics API rejected any size parameter above 10,000 with size parameter cannot exceed 10000 (Elasticsearch max_buckets limit), so customers with more than 10,000 unique owners or groups could not retrieve a complete breakdown through the API at all. The ceiling is now 65,536, and the error text names the real setting (search.max_buckets) and value. Calls with size of 10,000 or below are unaffected.
Index Selection & Alias Resolution
A top path or an entire index could be absent from search scope, dashboards, charts, and reports while the UI looked entirely normal. Several of the documented cases could even worsen as repeat scans accumulate, so a deployment that behaved correctly could begin dropping visual data with no configuration change.
[DEV-1214]
With "Always use latest indices" enabled, an entire top path could vanish from the index selection when two scans produced index names that differed only by their datestamp suffix. Candidate indices were previously narrowed by index name before any index metadata was read, and name similarity is not the same as top-path coverage. Auto selection now reads actual top-path coverage from index metadata and keeps, for each top path, the newest completed index covering it as well as the newest in-progress index covering it, preserving the existing rescan-in-flight fallback.
[DEV-1215]
Also in "Always use latest indices" mode, under specific circumstances a valid but older index could remain selected as "latest," so users read stale figures believing they were current and after toggling selection mode again, that top path could disappear from the selection entirely. Which outcome occurred depended on session age and the order in which auto and manual mode had been toggled, not on the data. The latest-index-per-top-path map is now derived once from complete state and compared on the crawl start time, instead of being merged from partial recomputes. Sessions affected by the previous behavior are expected to self-heal on their first recompute; a fresh login is not required.
[DEV-1216]
An index whose name was a substring of another selected index's name (for example diskover-exif alongside diskover-exif-gps) could be silently omitted from the resolved search scope. The index list was being de-duplicated with a substring test only and has now been updated to be an exact string match.
[DEV-1218]
Selecting an index alias and a plain index together caused the plain index to silently fail to display data: its top paths were missing from the top-path menu, its hits were missing from Global View search, and it was absent from the global dashboards, charts, and last-indexed tooltips. Alias resolution replaced the entire selection with the alias's backing indices instead of substituting only the entries that were actually aliases. Each selected entry is now resolved independently, with de-duplication.
[DEV-1130]
On deployments where the active index selection resolved to an index alias, the first page load after login returned an HTTP 500 error; refreshing loaded the UI normally, and the error recurred once per new login session. This was caused by a leftover restore block referencing a legacy variable removed in 2.4.3, which assigned a null value that then reached a strictly-typed function. The block has been removed.
[DEV-1110]
On the Select Indices page, an index scanning multiple top-paths whose crawl was still running could be selected as long as at least one of its top paths had finished, and searches then ran against a partially built index. Selectability now uses the same readiness list the API uses, and it is enforced at three points: the checkbox, the form save, and the index= / index2= URL parameters. In-progress indices remain visible on the page (disabled) so administrators can still monitor and force-delete them.
Task Scheduling, Locking & Crawl Lifecycle
[DEV-1076]
On large or highly active deployments, scheduled crawls could fail to fire during their allotted schedule window. Each worker evaluated schedules in its own poll loop and a task was considered due only during its scheduled minute, if the workers were at capacity and didn’t free up a slot within that minute window the calls were silently dropped. Worker claim capacity per minute is configuration bounded, and long crawls hold slots for the length of their run time, so scheduled overflow tasks could routinely lost. A task is now due until it actually runs, and catch-up coalesces automatically: only the most recent missed occurrence runs, so a backlog cannot stack up.
[DEV-1147]
A single task could be claimed and run concurrently by two or more workers, producing multiple simultaneous indices for one task with no user action. Redundant scans consumed storage and worker capacity and left indices incomplete. The task start lock is now arbitrated by the database through a conditional update rather than inferred by writing and re-reading, the claim is taken immediately before the task is marked as starting rather than at enqueue time, and the admin service re-checks the task's status under the lock and refuses a claim that would duplicate a run.
[DEV-1148]
Using Reset Status (Clear Status) on a task whose crawl was still running re-armed the task and started a second concurrent crawl of the very task the operator was trying to tidy up. In bulk, one request could duplicate many tasks. Reset Status and Run Now now refuse and provide operator guidance when the task is provably running: its stored status is in flight, its worker has reported recently, and that worker lists the task as currently running. If the worker is dead, restarted, or not reporting, the action still goes through, so a genuinely wedged task can always be cleared. Rows whose worker has stopped reporting now show a worker offline badge with the elapsed time, and bulk actions report how many tasks were updated and how many were skipped, with a reason for each.
[DEV-1152]
Deleting an index while it was still being built did not gracefully stop the crawl. The crawler kept writing, Elasticsearch re-created the index on the next write, and what came back had incomplete metadata that would block it from appearing on the Indices page at all and could not be seen, selected, or deleted through the product while it continued to consume cluster storage. Crawl writes now target a crawl-private alias that is removed along with the index, so deleting an in-progress index causes the very next write to be rejected and the crawl to abort with the cause reported.
Search, Dashboards & File View
[DEV-1112]
Clicking a segment in a Global View dashboard widget returned "Sorry, no items found" whenever the clicked file type did not happen to exist in the index currently chosen in the index selector. Global drill-down links request all top paths, but that request was falling back to the single selected index. Global drill-downs now search the union of every top path's index — the same scope the widget itself aggregates over — and the scope survives pagination, sort changes, and clicks on the extension filter row.
[DEV-1073]
For a user restricted by Index Access, a wildcard index expression such as diskover-* returned an HTTP 502 with an Elasticsearch too_long_http_line_exception. Administrators were unaffected, so the failure appeared arbitrary. The expanded list of accessible index names was being placed in the request URL, which exceeded Elasticsearch's default 4096-byte request-line limit at high index counts. The restriction now travels in the request body as a filter on the index metadata field, so the wildcard expression stays intact and the authorization boundary is unchanged.
[DEV-1339]
File View returned a blank page for any document whose configured extra field held the boolean value true — the dupes plugin's is_dupe field being the usual trigger. The page was comparing the extra field's value against 'ctime' where it meant to compare the field's name, and as a result every boolean-true extra field took the timestamp-formatting branch and threw a fatal error. Files where the field was false or absent rendered normally, which made the crash look random. The comparison now tests the field name with strict equality, and a boolean field renders as true with a working search link.
Authentication & Directory Services
Four LDAP defects are fixed in this release. Sites using LDAP should read this section together with the corresponding Upgrade Notes before rolling out.
[DEV-1344]
In standard Active Directory mode and Alt Bind 2 mode the user lookup was scoped to LDAP Groups DN, the container that holds groups. On the ordinary directory layout, where users and groups sit in sibling containers, the search matched nothing, the group list came back empty, and every LDAP user was denied with "Access denied. Your account is not a member of any authorized group." The symptom pointed administrators at their group lists rather than at the search base. The user lookup is now scoped to LDAP Users DN (falling back to the base DN when that setting is blank) for the modes whose filter matches a user entry, and continues to use LDAP Groups DN for Alt Bind 1 and Alt Bind 3, whose filters match group objects. The nested path was aligned to the same base. The LDAP debug log now names which setting supplied the search base, so a misconfigured DN is diagnosable from the log rather than by inference.
[DEV-1338]
On directories that publish groups with a multi-valued RDN cn=<name>+gidNumber=<gid> (occasionally seen on POSIX-style directories such as OpenLDAP, 389 Directory Server and eDirectory), group names were being derived as <name>=<gid> rather than <name>. That string matched neither the group names stored in the index nor the group names configured in Diskover Admin, so group-based login authorization and group-based permission filtering both stopped working for affected users after upgrading from 2.4.x with no configuration change. The reported consequence was that every directory with group-only permissions vanished for non-admin users while world-readable directories stayed visible, and that sites could only restore login by adding the malformed strings to their group lists. Group DNs are now parsed properly rather than split on the first comma and equals sign, which additionally handles escaped separators and hex escapes in group names. Active Directory group DNs are single-valued, so AD sites never saw this. Sites that added <name>=<gid> entries as a workaround are now directed to remove them — see Upgrade Notes.
[DEV-1131]
If the total LDAP exchange took longer than 30 seconds, the login page reported that the authentication service could not be reached even though the authentication engine was found to have ran to completion and logged a successful authentication. The user could not log in, and nothing in any log indicated a timeout. A new LDAP Timeout (LDAP_TIMEOUT) setting, default 55 seconds, has been added to the LDAP configuration page that covers the scope for an entire login attempt: connect, bind, and all group searches combined. The web request timeout is derived from it, so the engine always fails before the caller does, and timeouts now produce an actionable error naming the setting to adjust. A warning is logged when a login consumes more than 80% of the budget, and the Diskover Admin help text for LDAP Groups DN and LDAP Nested Groups now explains that recursive group search over a broad base DN is expensive on Active Directory.
[DEV-1265]
LDAP group membership calls could return empty for Active Directory customers: users authenticated successfully but received no groups, so every group-based authorization decision failed. Active Directory returns the memberOf attribute in its schema casing regardless of how it is requested, and the attribute was being read with a case-sensitive lowercase key. Attribute lookup is now case-insensitive, which covers Active Directory, lowercase-responding servers, and any other casing a directory returns. Customers who applied a local patch to ldap.py for this should revert it and take the shipped fix, which is broader.
Security & Access Control
[DEV-1151]
Task Panel actions — Run Now, Stop, Force Stop, Reset Status, Enable, Disable, Delete, Clone, along with worker enable/disable/remove, template delete, and clear task log — were state-changing HTTP GET requests with no CSRF protection. Any replay of such a URL in an authenticated operator's browser executed the action with the operator's full privileges and no confirmation: a restored or refreshed tab, back/forward navigation, browser prefetch, or a cross-site link. Combined with the duplicate-run defect above, an unintended Run Now on an already-running task could produce a second concurrent crawl.
These endpoints now require three independent conditions on every state change: the POST method, a matching same-origin Origin/Referer, and a per-session random CSRF token bound to the session ID and compared in constant time. A one-release compatibility path allows non-browser callers (scripts using curl, wget, or similar) to continue using GET this release; browser GETs are rejected. See Upgrade Notes for the migration path and the audit log that identifies affected scripts.
AI Data Assistant (MCP)
[DEV-1118]
Asking the assistant for the latest indices returned them out of chronological order, and the response carried no date field, so the assistant had only index-name substrings from which to infer recency. The MCP server was re-sorting the API's newest-first response alphabetically. That re-sort has been removed. The list_indices tool was reworked in the same change: rows are now ordered by newest crawl end time and each row carries a crawl_end_time value.
[DEV-1126]
An MCP remote server running under systemd produced no logs or journal entries at all, regardless of the configured log level. To remedy this, the Transport selection is now driven by declared configuration. Console logging is always installed, so output reaches journalctl -u diskover-mcp-server (errors and warnings on standard error; in stdio mode every level goes to standard error so that standard output carries only the protocol stream). File logging writes rotating error.log and combined.log files — 5 MB per file, five files retained — to the directory named by LOG_DIR. An unwritable log directory now produces an explicit error naming the setting to fix instead of failing silently. See Upgrade Notes.
Administration & Serviceability
[DEV-1221]
The diskover-admin service unit discarded both standard output and standard error, so any failure occurring before the file logger came up produced no diagnostics anywhere. Error output is now routed to the systemd journal, while routine informational output is moved to standard output and remains suppressed, preserving the prior behavior that keeps ordinary Diskover logging out of the system log. Uvicorn's pre-initialization debug logging has also been removed, and a start that dies before the socket appears now aborts with a message instead of waiting indefinitely.
[DEV-1222]
Every stop of an admin service was recorded by systemd as a failure, so routine restarts looked like crashes in the journal and to any monitoring watching unit results. Due to an error in the RPM build process the installed unit ended up with no process argument, which exits immediately with "not enough arguments". envsubst is now restricted to ${VERSION}, so $MAINPID reaches the generated unit intact.
[DEV-1287]
The unauthenticated diskover-admin /ping health endpoint now also reports the product version. Every other admin API endpoint requires authentication, so a client had no way to distinguish an older server from a rejected credential. The response is now {"status": true, "result": "pong", "version": "2.6.1"}; the version key is additive and the existing keys are unchanged. The Python version string has also been consolidated into a single shared module.
[DEV-1193]
Three scan settings were unintentionally enabled by default as part of a 2.6.0 change; restoretimes, fileagegroups, and rolluptimes. They have been reverted to disabled by default, their pre-2.6.0 state. The settings themselves are unchanged and remain available under Advanced Fields in Diskover Admin. See Upgrade Notes.
Upgrade Notes
Read first
Upgrade the admin service before the workers, or in the same maintenance window. Never upgrade workers first. The guard that rejects a stale duplicate task claim (DEV-1147) is enforced by the admin service; under 2.6.1's sticky scheduling (DEV-1076), a workers-first rollout can re-run completed scheduled fires for the duration of the mixed-version window on a busy fleet.
Crawl writes now depend on the Elasticsearch require_alias write option (DEV-1152), which is available from Elasticsearch 7.10 onward and in all OpenSearch releases. There is no fallback path for backends that do not support it. Deployments running an Elasticsearch version earlier than 7.10 should confirm compatibility before upgrading.
Sites using LDAP should review the Authentication section before rolling out. Two of the four LDAP fixes change which container the directory is searched for a user entry and how group names are derived from a DN. Both correct outright access failures, and both mean that workarounds put in place on 2.6.0 should now be removed — see Configuration and environment below.
Expect a one-time burst of catch-up scans on the first worker start after upgrade. Because scheduled fires are now sticky, any enabled task whose most recent scheduled fire postdates its last start and finish becomes due immediately and runs once — including never-run tasks whose fire was missed while workers were down. Only the latest missed occurrence runs per task, but on a large worker fleet this will look like a stampede in the task list.
Numbers that will legitimately change
Size and cost figures on the Metrics API, the tag size API, the Tags page, and the Cost Analysis page will read lower after upgrading, against the same un-rescanned data. Nothing was lost and no rescan is required, directory rollups are now reported beside file totals instead of being added into them. Specifics that can affect automation:
tagsizedefault changed. Thetypeparameter now defaults tofilerather than the combined file-and-directory sum. An explicittype=(file OR directory)is coerced tofile; callers wanting both figures must issue two calls.overall_stats.total_countin the Metrics API now counts file documents only. Callers reading it as "items in scope" should useoverall_countsinstead. A newdirectory_statsblock has been added; existing keys are unchanged.CSV exports gained columns. The Tags and Cost Analysis "Show all" exports now include directory rollup columns. Anything parsing those exports by column position must be reviewed.
Task Panel actions now require POST
Task Panel action endpoints reject browser GET requests with HTTP 405 and POST requests without a valid CSRF token with HTTP 403. Bookmarks and saved links to these URLs stop working.
Scripts have one release to migrate. Non-browser callers (curl, wget,
python-requests, and similar) continue to work this release and are logged. The GET path is scheduled for removal in the next release.Find affected scripts by grepping the PHP error log for the audit channel
[diskover-tasks audit]and the eventdeprecated.get, which records the path, query, and user agent of every legacy caller.Reverse proxies must set
X-Forwarded-HostandX-Forwarded-Protocorrectly. A proxy that rewritesHostto an internal address without settingX-Forwarded-Hostwill cause legitimate requests to be rejected with 403.
Changed defaults and removed functionality
Scan settings reverted to disabled (DEV-1193). Deployments that relied on
restoretimes(Restore Times),fileagegroups, orrolluptimesbeing on since 2.6.0 must re-enable them explicitly under Advanced Fields in Diskover Admin. Withfileagegroupsoff, new scans do not populate thefileagesfield on directory documents; withrolluptimesoff, they do not populatetimerollup. Dashboards, saved searches, and reports that depend on those fields will return empty results for newly scanned indices. Restore Times is particularly relevant to CIFS deployments that cannot use thenoatimemount option.These options have been in the product for some time but were forcefully enabled by default in the 2.6.0 release and may have resulted in slower than expected scan speeds under certain scanning conditions.
Index selection behavior
In auto-select mode, the Select Indices page now lists approximately one index per top path rather than two per index-name series; redundant older scans are hidden. Manual selection is unchanged.
Closed indices are no longer eligible for auto selection.
Existing sessions may require a page reload and a cache refresh immediately after upgrade, after which they re-seed normally.
Mixed alias and plain index selections will now show data that was previously missing, and the "last indexed" timestamp for a top path present in both may resolve differently.
Indices with a crawl still in progress can no longer be selected, including via
index=/index2=URL parameters. Saved links naming an in-progress index will report that the index is still being indexed.
Configuration and environment
New setting
LDAP_TIMEOUT(UI: LDAP Timeout, Advanced), default 55 seconds. The effective LDAP timeout therefore rises from a fixed 30 seconds to 55; sites that were failing between those two values will begin working with no configuration change. On Active Directory with nested groups enabled, ensure that LDAP Groups DN is properly scoped to the container holding the Diskover groups before raising this value.LDAP user lookups now use LDAP Users DN (DEV-1344). In standard Active Directory mode and Alt Bind 2, the user entry is searched under LDAP Users DN, falling back to the base DN when it is blank. Sites that widened LDAP Groups DN to a common ancestor of users and groups, blanked it, or enabled LDAP Nested Groups purely to make logins succeed can revert those changes after upgrading. Reverting Nested Groups is worth doing on large directories: it removes the chained group search that the LDAP timeout was compensating for. Alt Bind 1 and Alt Bind 3 are unchanged and remain scoped to LDAP Groups DN. Confirm LDAP Users DN is set correctly before upgrading, a wrong value produces the same "not a member of any authorized group" denial.
Remove
<name>=<gid>entries from your LDAP group lists (DEV-1338). Sites on POSIX-style directories that restored login by adding malformed group names such asSTORAGE_USERS=13579to the LDAP user or admin group lists in Diskover Admin must remove those entries after upgrading. Group names now resolve to the plaincn, so the workaround entries are dead and the real names will match. Group-based permission filtering will begin returning group-only directories that were previously hidden.Aggregation ceilings raised to 65,536 (DEV-1347, DEV-1348). The Metrics API
sizeparameter now accepts values up to 65,536 instead of 10,000, and its over-limit error namessearch.max_buckets. The User Analysis page requests up to 65,536 owners and groups. Calls and pages that stayed within the old 10,000 behave identically; sites with more than 10,000 unique owners will see rows appear that were previously dropped, and User Analysis percentages will shift accordingly. Owners beyond 65,536 are still dropped.Admin service stops no longer report a failure (DEV-1222). If you suppressed or ignored
Failed with result 'exit-code'ondiskover-adminstop in your monitoring, that suppression is no longer needed and will now mask real failures.http.max_initial_line_lengthno longer needs tuning. Sites that raised this Elasticsearch setting to work around restricted-user wildcard searches can return it to the 4096-byte default.MCP server: set
LOG_DIR. The recommended value is/var/log/diskover-mcp-server, which must match the service unit's writable path. Ansible-managed deployments have this added automatically on upgrade; hand-installed deployments must set it manually, or file logging is skipped and only journal/console logging is available. Docker deployments need no change: the image's default log directory is already/app/logs, which is where the documented volume mount points.Restricted users and paging. The
paging.modevalues scroll andsearch_after_piton the search endpoint now return HTTP 400 when the index expression resolves to more than one index. In 2.6.0 these modes silently returned results from the first matching index only. Integrations affected should switch topaging.mode: search_after, which pages across all accessible indices, or issue one request per concrete index. Discard pagination cursors issued before the upgrade and restart each walk without a cursor.The
diskover-adminsystemd unit is replaced on upgrade. Local edits to/usr/lib/systemd/system/diskover-admin.servicewill be lost. Place local overrides in a drop-in under/etc/systemd/system/diskover-admin.service.d/instead. Sites that adopted DEV-903 specifically to keep the system log clean will now see error-priority admin output in/var/log/messagesbut logging here is kept minimal; it is preferred to leveragejournalctlfor diagnosis.
Known limitations
Index orphans already stranded on a system before this upgrade are not cleaned up by DEV-1152. Removing them still requires direct Elasticsearch access.
A task hard-killed mid-run (SIGKILL, out-of-memory, or power loss) still remains at
startingorrunninguntil an operator clears its status. This is why the new Reset Status guard deliberately allows the action when a worker is not reporting.
Comments
0 comments
Please sign in to leave a comment.