Fix for Windows client 2.5.32 stuck indexing after USN rollover

Hi,

I had a Windows client stuck at “Indexing…” for several hours. I used Codex to investigate the client and server logs, NTFS journal state, process activity and the client’s SQLite database. Codex also applied the index workaround described below. Am sharing the fix in case it helps others. The following was drafted by Codex.

Setup

  • Client: UrBackup 2.5.32

  • Server: UrBackup 2.5.37 on Windows

  • Client OS: Windows 11 Business x64, build 26200

  • Filesystems: NTFS on C: and D:

  • Client name: vt-overseer

The client had been unable to reach the server for about two weeks. During that time I migrated Windows profiles and did a lot of development work, often with several Claude and Codex agents running concurrently. This produced substantial file and directory churn.

Symptoms

The server remained at:

Starting unscheduled full file backup...
vt-overseer: Connecting for filelist...
vt-overseer: Waiting for filelist
vt-overseer: Connecting for filelist (async)...

The UI showed “Indexing… 0%” with no useful progress. Eventually the local client reported:

There was an error. Currently nothing can be backed up.

UrBackup continuously occupied about one logical CPU core and performed roughly 1.1 GB/s of cached reads, but there was little physical disk activity and no backup transfer.

A clean reinstall and recreation of the client database did not prevent the problem from returning.

What Codex found

The 1 GB NTFS USN journal on C: had rolled over several times. UrBackup’s saved position had fallen behind the oldest available record, so it needed to rebuild its index.

During the failed reindex, the client database contained approximately:

mdirs:      465,953 rows
del_dirs:   463,093 rows
map_frn:    861,418 rows

Codex found these queries in the UrBackup 2.5.32 source:

INSERT INTO mdirs (name)
SELECT ? AS name
WHERE NOT EXISTS (
    SELECT * FROM mdirs WHERE name=?
);

INSERT INTO del_dirs
SELECT ? AS name
WHERE NOT EXISTS (
    SELECT * FROM del_dirs WHERE name=?
);

Source:

https://github.com/uroni/urbackup_backend/blob/2.5.32client/urbackupclient/DirectoryWatcherThread.cpp#L64-L65

The client database had no index on mdirs(name) or del_dirs(name). SQLite’s query plans showed full table scans for these existence checks.

Workaround

After stopping the client and confirming that PRAGMA quick_check returned ok, Codex added:

CREATE INDEX IF NOT EXISTS idx_mdirs_name
ON mdirs(name);

CREATE INDEX IF NOT EXISTS idx_del_dirs_name
ON del_dirs(name);

The query plans then used covering indexes. After restarting the client, C: and D: both reached index_done=1 by the second 15-second check, and the file backup began transferring normally.

At the same time, Codex increased the C: and D: USN journals from 1 GB to 4 GB and removed three stale UrBackup VSS snapshots.

This was not a controlled test where each change was applied separately, so I cannot say with certainty that the indexes alone fixed it. However, the before and after query plans, the sustained cached-read load and the immediate improvement make the missing indexes the strongest explanation.

Would it make sense to add these indexes to the standard client database schema or its migration process?

The UI could also report the indexing stages more clearly. It continued showing “Indexing… 0%” even after the journal state showed index_done=1.

I found older threads about backups getting stuck at indexing, but none that discussed these two tables or their query plans.

I have the client and server logs, database statistics and before and after query plans. The logs contain local paths, so I can send them to bugreports@urbackup.org and reference this thread.