Release: 2.4.0.0 (Stable) 2026-09-03

I’m Adam from the recovery thread that @mr-flibble linked above:

Need recovery advice after 2.3.0.0 issue: recreate found 36 broken filelists, purge dry-run fails

I can confirm that my experience was extremely similar. With a roughly 27 GB Duplicati database, repair validation caused Duplicati.CommandLine.exe to consume around 66–68 GB of virtual memory. It happened on two different Windows computers, so it wasn’t specific to the lower-powered machine I first used.

Setting:

CUSTOMSQLITEOPTIONS_DUPLICATI=temp_store=FILE

dramatically reduced the memory usage and allowed the repair to complete. I eventually recovered the backup, but it took several multi-day recreates, removing 36 affected restore points, and repairing a dangling database relationship. A successful backup finally completed on 20 June.

Seeing the same workaround take @mr-flibble from 16 OOM kills to zero makes this look like a general large-database SQLite temp-storage problem, rather than something peculiar to my setup.

Since 2.4.0.0 still appears to default to temp_store=MEMORY, could this please become a tracked issue? Would it make sense for Duplicati to use disk-backed temporary storage automatically for large databases or known heavy maintenance queries—or, at minimum, document this workaround prominently?

I’m happy to provide the original logs and further technical details if they would help identify the query.

I deleted Duplicati in order to update to 2.3, but never installed it. I now dowloaded duplicati-2.4.0.0_stable_2026-09-03-win-x64-gui.msi and attempted installation. It failed immediately with message “Duplicati Setup: The installer has encountered an unexpected error installing this package. This may indicate a problem with this package. The error code is 2812.”
Any help?

This error means something inside the package is not working.
Could you try this:

msiexec /i "C:\path\to\installer.msi" /L*V "C:\path\to\install.log"

Then send me the install.log file via a PM, and I will have a look.

It’s a huge backup, profiling produces an insanely large log file that contains sensitive data, so i cannot provide the full log unfortunately. But here is where it stalls and starts to eat all the RAM, copied from the UI, newest line first:

Sep 18, 2026, 9:20:17 PM Starting - ExecuteNonQueryAsync: CREATE TEMPORARY TABLE "UsageReport-A8DB095669A...
Sep 18, 2026, 9:20:17 PM No remote filesets should be deleted...

Here is the full query:

Starting - ExecuteNonQueryAsync: CREATE TEMPORARY TABLE "UsageReport-A8DB095669A21841AAA88B154D120C1F" AS 
                SELECT
                    "VolumeID" AS "VolumeID",
                    SUM("ActiveSize") AS "ActiveSize",
                    SUM("InactiveSize") AS "InactiveSize",
                    MAX("Sorttime") AS "Sorttime"
                FROM (
                SELECT
                    "A"."ActiveSize" AS "ActiveSize",
                    0 AS "InactiveSize",
                    "A"."VolumeID" AS "VolumeID",
                    CASE
                        WHEN "B"."Sorttime" IS NULL
                        THEN 0
                        ELSE "B"."Sorttime"
                    END AS "Sorttime"
                FROM (
                SELECT
                    SUM("Block"."Size") AS "ActiveSize",
                    "Block"."VolumeID" AS "VolumeID" FROM "Block",
                    "Remotevolume"
                WHERE
                    "Block"."VolumeID" = "Remotevolume"."ID"
                    AND "Block"."ID" NOT IN (
                        SELECT "Block"."ID"
                        FROM
                            "Block",
                            "DeletedBlock"
                        WHERE
                            "Block"."Hash" = "DeletedBlock"."Hash"
                            AND "Block"."Size" = "DeletedBlock"."Size"
                            AND "Block"."VolumeID" = "DeletedBlock"."VolumeID"
                    )
                    GROUP BY "Block"."VolumeID"
            ) "A"
                LEFT OUTER JOIN (
                SELECT
                    "VolumeID" AS "VolumeID",
                    MIN("Sorttime") AS "Sorttime"
                FROM (
                    
                SELECT
                    "Block"."VolumeID" AS "VolumeID",
                    "Fileset"."Timestamp" AS "Sorttime"
                FROM
                    "Fileset",
                    "FilesetEntry",
                    "FileLookup",
                    "BlocksetEntry",
                    "Block"
                WHERE
                    "FilesetEntry"."FileID" = "FileLookup"."ID"
                    AND "FileLookup"."BlocksetID" = "BlocksetEntry"."BlocksetID"
                    AND "BlocksetEntry"."BlockID" = "Block"."ID"
                    AND "Fileset"."ID" = "FilesetEntry"."FilesetID"
            
                    UNION 
                SELECT
                    "Block"."VolumeID" AS "VolumeID",
                    "Fileset"."Timestamp" AS "Sorttime"
                FROM
                    "Fileset",
                    "FilesetEntry",
                    "FileLookup",
                    "BlocksetEntry",
                    "Block",
                    "Metadataset"
                WHERE
                    "FilesetEntry"."FileID" = "FileLookup"."ID"
                    AND "FileLookup"."MetadataID" = "Metadataset"."ID"
                    AND "Metadataset"."BlocksetID" = "BlocksetEntry"."BlocksetID"
                    AND "BlocksetEntry"."BlockID" = "Block"."ID"
                    AND "Fileset"."ID" = "FilesetEntry"."FilesetID"
            
                )
                GROUP BY "VolumeID"
            ) "B"
                    ON "B"."VolumeID" = "A"."VolumeID"
              UNION 
                SELECT
                    0 AS "ActiveSize",
                    SUM("Size") AS "InactiveSize",
                    "VolumeID" AS "VolumeID",
                    0 AS "SortScantime"
                FROM "DeletedBlock"
                GROUP BY "VolumeID"
             UNION 
                SELECT
                    0 AS "ActiveSize",
                    0 AS "InactiveSize",
                    "Remotevolume"."ID" AS "VolumeID",
                    0 AS "SortScantime"
                FROM "Remotevolume"
                WHERE
                    "Remotevolume"."Type" = "Blocks"
                    AND "Remotevolume"."State" IN ("Uploaded", "Verified")
                    AND "Remotevolume"."ID" NOT IN (
                        SELECT "VolumeID"
                        FROM "Block"
                    )
            )
                GROUP BY "VolumeID"
            

I have another data point for the large-database SQLite performance issue.

My normal Windows 2.4.0.0 job backs up over SFTP/SSH to a Raspberry Pi 5 on my local Ethernet network, with the repository on its attached 4 TB disk. It completed successfully today, so this is not a repeat of my earlier broken-filelist/recovery incident. However, it took 7:24:23 to back up 831.9 GB / 1,195,804 examined files, uploading only 116.9 MiB of changes. The job has 420 versions and a 27.6 GB local database.

This is also consistent rather than isolated: the last nine completed runs took 5:00, 5:26, 6:04, 6:52, 7:24, 8:38, 9:01, 9:37 and 11:47. The median is about 7 hours 24 minutes. Most uploaded only a few hundred MiB of changed data, while downloading roughly 5.4–6.3 GiB for verification/maintenance.

CUSTOMSQLITEOPTIONS_DUPLICATI=temp_store=FILE is already enabled, with the local database and temp directory on E:. So it did not run out of memory; instead, the slow-query monitor showed the work moving to disk:

  • SELECT "ID" FROM "Fileset" was still running after 6,260 seconds.
  • The CREATE TEMPORARY TABLE "UsageReport-..." AS ... query was still running after 9,735 seconds.

The run completed with zero errors, but spent 3:02:55 in the compact/report phase. Compaction itself said it was not required, so this does not look like the old-version deletion path addressed by PR #7320. It looks closer to another large-database query/reporting bottleneck.

I can provide the full slow-query text and profiling log if that would help identify the query plan.

I’m also experiencing high memory load in a dockerized setup with the normal (non Linuxserver) image. According to Grafana Dashboard the memory consumption went up to 5GB, right after the backup jobs started and never went down again after they finished. Is there a chance that the fix you proposed will make it to a new stable (Bugfix) Version soonish or should I switch to canary until a new stable is being released?