I have Delta Chat on my desktop and I am trying to add it to my laptop. The QR code workflow does not work for me as neither device has a camera. I started following the “manual transfer” process here and a progress meter flashes very briefly before closing, then I see a red overlay with this error message: could not export database: failed to attach backup database: disk I/O error: Error code 3850: I/O error in the advisory file locking layer.
I am running Debian with a window manager started via exec dbus-run-session cwm in my .xinitrc. Delta Chat is installed through flatpak and run with flatpak run chat.delta.desktop. When I get the error nothing is printed in the terminal from which the command is run.
Any help is appreciated! I’m about to go on a week-long trip and I was really hoping to be able to access Delta Chat while I’m away.
Thank you for reporting the issue and I’m sure others here can help debug your issue further.
As a stopgap, you can create a backup file yourself manually (sorry about the hack). First, enable Multi-Device Mode in the settings on both devices under Advanced. Then exit Delta Chat and wait for it to stop.
First find your data folder with find ~ -name dc.db
Copy dc.db and dc.db-blobs to a new folder. Rename dc.db there to dc_database_backup.sqlite and the folder to $BLOBDIR under a new folder blobs_backup. Then compress these two with tar -cvf delta-chat-backup-2026-09-07-00-something@somewhere.tar dc.db blobs_backup (i.e., it should not contain an extra containing folder) You can then transfer the file over USB MTP or another private way.
(3850) SQLITE_IOERR_LOCK
The SQLITE_IOERR_LOCK error code is an extended error code for SQLITE_IOERR indicating an I/O error in the advisory file locking logic. Usually an SQLITE_IOERR_LOCK error indicates a problem obtaining a PENDING lock. However it can also indicate miscellaneous locking errors on some of the specialized VFSes used on Macs.
By the way, Delta Chat backup exporting does work with eCryptfs on Ubuntu, so it might be something else Mint-specific.
It looks like I am actually having problems at both ends, i.e. in generating the backup in on my primary device and in restoring from backup on my secondary device. Both are PCs running Debian as I describe in my original post.
I couldn’t figure out what to put for $BLOBDIR so I just used that string literally. Here is what I have in my backup file:
I then installed and ran Delta Chat using Flatpak on my second device. Here’s what it prints:
$ flatpak run chat.delta.desktop
Note that the directories
'/var/lib/flatpak/exports/share'
'/home/cm/.local/share/flatpak/exports/share'
are not in the search path set by the XDG_DATA_DIRS environment variable, so
applications installed by Flatpak may not appear on your desktop until the
session is restarted.
F: Can't get document portal: GDBus.Error:org.freedesktop.DBus.Error.NoReply: Message recipient disconnected from message bus without replying
Logfile: /home/cm/.var/app/chat.delta.desktop/config/DeltaChat/logs/2026-09-14-22-45-45.log
init: 713.237ms
A Delta Chat window pops up, I click “I Already Have a Profile,” then “Restore from Backup,” then select delta-chat-backup-2026-09-14-00-something@somewhere.tar. The file selection menu then disappears, leaving the “I Already Have a Profile” modal with no indication of success or failure. Nothing shows up in the log file ~/.var/app/chat.delta.desktop/config/DeltaChat/logs/2026-09-14-22-45-45.log. This could be a problem with the format of the manually generated backup file, or a problem with the way I am running Delta Chat.
Here is the output of mount on the primary device which shows the “could not export database” error when I try to export a backup:
$ mount
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime)
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
udev on /dev type devtmpfs (rw,nosuid,relatime,size=8114892k,nr_inodes=2028723,mode=755,inode64)
devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000)
tmpfs on /run type tmpfs (rw,nosuid,nodev,noexec,relatime,size=1631668k,mode=755,inode64)
/dev/sda3 on / type ext4 (rw,relatime,errors=remount-ro)
securityfs on /sys/kernel/security type securityfs (rw,nosuid,nodev,noexec,relatime)
tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev,inode64)
tmpfs on /run/lock type tmpfs (rw,nosuid,nodev,noexec,relatime,size=5120k,inode64)
cgroup2 on /sys/fs/cgroup type cgroup2 (rw,nosuid,nodev,noexec,relatime,nsdelegate,memory_recursiveprot)
pstore on /sys/fs/pstore type pstore (rw,nosuid,nodev,noexec,relatime)
bpf on /sys/fs/bpf type bpf (rw,nosuid,nodev,noexec,relatime,mode=700)
systemd-1 on /proc/sys/fs/binfmt_misc type autofs (rw,relatime,fd=29,pgrp=1,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=1000)
mqueue on /dev/mqueue type mqueue (rw,nosuid,nodev,noexec,relatime)
hugetlbfs on /dev/hugepages type hugetlbfs (rw,relatime,pagesize=2M)
debugfs on /sys/kernel/debug type debugfs (rw,nosuid,nodev,noexec,relatime)
tracefs on /sys/kernel/tracing type tracefs (rw,nosuid,nodev,noexec,relatime)
configfs on /sys/kernel/config type configfs (rw,nosuid,nodev,noexec,relatime)
ramfs on /run/credentials/systemd-sysctl.service type ramfs (ro,nosuid,nodev,noexec,relatime,mode=700)
fusectl on /sys/fs/fuse/connections type fusectl (rw,nosuid,nodev,noexec,relatime)
ramfs on /run/credentials/systemd-sysusers.service type ramfs (ro,nosuid,nodev,noexec,relatime,mode=700)
ramfs on /run/credentials/systemd-tmpfiles-setup-dev.service type ramfs (ro,nosuid,nodev,noexec,relatime,mode=700)
ramfs on /run/credentials/systemd-tmpfiles-setup.service type ramfs (ro,nosuid,nodev,noexec,relatime,mode=700)
binfmt_misc on /proc/sys/fs/binfmt_misc type binfmt_misc (rw,nosuid,nodev,noexec,relatime)
tmpfs on /run/user/1000 type tmpfs (rw,nosuid,nodev,relatime,size=1631664k,nr_inodes=407916,mode=700,uid=1000,gid=1000,inode64)
gvfsd-fuse on /run/user/1000/gvfs type fuse.gvfsd-fuse (rw,nosuid,nodev,relatime,user_id=1000,group_id=1000)
portal on /run/user/1000/doc type fuse.portal (rw,nosuid,nodev,relatime,user_id=1000,group_id=1000)
As far as I know this is what Debian 12 gives you by default. If there’s anything unusual about my setup it’s the lack of a desktop environment with integrated D-Bus support, so that to run Delta Chat I had to start my window manager with dbus-run-session.
This is how backup generated by DC (development version, so there is a fingerprint instead of an email address now in the filename, but otherwise it is the same) looks like:
$ tar tf delta-chat-backup-2026-09-15-00-AC6891014021C9F08A3BD3E218DF90190DCB9143.tar
dc_database_backup.sqlite
blobs_backup/$BLOBDIR/40c5793b03b631a57020323f0f10bfa
blobs_backup/$BLOBDIR/c2ab10c1dba5170d19c9f3998f095b0.png
blobs_backup/$BLOBDIR/91f9bc261758b09b57844798ebb61f1.jpg
blobs_backup/$BLOBDIR/969142cb84015bc135767bc2370934a.png
$BLOBDIR is a literal $BLOBDIR filename, so your backup file looks correct, with the exception that DC does not add $BLOBDIR as a separate entry.
This might be the real reason:
“Desktop portal” is needed for flatpak apps to access files outside of the flatpak I think. Maybe you need to install xdg-desktop-portal package and make sure xdg-document-portal.service is started? EDIT: portal on /run/user/1000/doc in mount output probably means it is.
The one that is actually required for accessing the files I think is the “desktop portal” rather than “document portal”, but if you get a file selection dialog then it is likely already working.
I tried stopping document portal locally, but got a different error: “file:///app/delta/resources/app/src/components/Settings/Backup.tsx:93:13” “backup-export failed:” {“code”:-1,“message”:“Transport endpoint is not connected (os error 107)”}
Here is what I see in the log when successfully exporting a backup:
2026-09-15T06:22:33.217Z core/event INFO "" 1 "src/imex.rs:158: Export path: /run/user/1000/doc/debf6TFuweaJrMbz3RV_nw/foobar"
2026-09-15T06:22:33.217Z core/event INFO "" 1 "src/sql.rs:990: Start housekeeping..."
2026-09-15T06:22:33.217Z core/event INFO "" 1 "src/sql.rs:1051: 4 files in use."
2026-09-15T06:22:33.218Z core/event INFO "" 1 "src/sql.rs:775: Incremental vacuum freed 0 pages."
2026-09-15T06:22:33.218Z core/event INFO "" 1 "src/sql.rs:682: wal_checkpoint: Total time: 3.118902ms. Writers blocked for: 230.755µs. Readers blocked for: 145.13µs."
2026-09-15T06:22:33.220Z core/event INFO "" 1 "src/sql.rs:921: Housekeeping done."
2026-09-15T06:22:33.527Z core/event INFO "" 1 "src/imex.rs:460: Backup '/home/user/.var/app/chat.delta.desktop/config/DeltaChat/accounts/b0127be9-bf09-4ae8-b252-791256dc6132/dc.db' to '/run/user/1000/doc/debf6TFuweaJrMbz3RV_nw/foobar/delta-chat-backup-2026-09-15-00-bn14kdyur@nine.testrun.org.tar'."
/run/user/1000/doc is the FUSE filesystem, but apparently where backup is exported to does not need locking, we just write a .tar archive there.
In my case backup is exported from /home/user/.var/app/chat.delta.desktop/config/DeltaChat/accounts/b0127be9-bf09-4ae8-b252-791256dc6132/dc.db and this path is on a real ext4.
@bleb Could you check the log file for the path from which the backup is exported? Maybe in your case backup is somehow exported via fuse.portal filesystem and the whole app is running from a FUSE mount? In may case it looks like Delta Chat exports directly from ext4.
I am using xdg-destktop-portal-gtk, maybe the problem is with a different portal implementation.
Moving my .xinitrc to .xsession which should cause startx to run the default /etc/X11/xinit/xinitrc which by extension sources the files under /etc/X11/Xsession.d/, including 20dbus_xdg-runtime and 20flatpak which seemed relevant.
Purging xdg-desktop-portal-gtk which was previously running, based on this reddit post.
Updating and rebooting.
I tried exporting a backup from Delta Chat multiple times while I was making these changes, with no success. Sometimes the 3850 error would be shown on the screen and sometimes it wouldn’t. When I tried just now, I did not get the 3850 error and nothing about any “portal” service or the dc.db path shows up in journalctl or in the log file under ~/.var/app/chat.delta.desktop/config/DeltaChat/logs. Running systemctl --user status xdg-desktop-portal shows Active: inactive (dead) and I’m not sure if that’s expected or where I would look for an error if it’s not expected. The one error message I see is printed by the flatpak command when Delta Chat starts up:
[2:0918/130845.027904:ERROR:dbus/object_proxy.cc:572] Failed to call method: org.freedesktop.DBus.Properties.Get: object_path= /org/freedesktop/portal/desktop: org.freedesktop.DBus.Error.InvalidArgs: No such interface “org.freedesktop.portal.FileChooser”
I am happy to try more things if anyone has suggestions.
Thankfully, I was able to add my laptop as a secondary device with the following steps:
On my primary device, select “Add Second Device”, then when the QR code is displayed click the three dots and “Copy”.
Paste the string into a file on my NAS.
Open the file on my second device and copy it.
In Delta Chat on my second device, select “I Already Have a Profile” and “Add as Second Device”, then click the gear icon and “Paste from Clipboard”.
It would be good to solve the original error, but it would also have saved me a lot of time if this procedure was described under https://delta.chat/en/help#multiclient.
I also think it would improve the UI to have text fields for viewing and entering the QR code string, rather than just clipboard operations. Anyone doing this workaround will want to see what they are copying anyway, and if someone decides to copy the string manually it avoids the dance of typing it into a file and then copying it to the clipboard.
I have debugged the problem by installing Debian 12 in a virtual machine.
tl;dr is that you need to upgrade xdg-desktop-portal to at least version 1.19.0. It is only available in Debian 13, so you need to upgrade to Debian 13.
I had to add “-display sdl” and install qemu-ui-sdl Arch package, otherwise QEMU tried to open VNC port instead of the UI. -m 2G is needed because with default settings Linux fails to boot with “initramfs unpacking failed” error.
I selected “Start installer” in the boot menu (rather than live image). When installing selected default options for everything. When partitioning the disk selected “All files in one paritition” option because I did not see separate /home in the mount output.
Then installed cwm 7.1-1, X.org, xterm and Flatpak with “apt install cwm xorg xterm flatpak”. I have then put exec dbus-run-session cwm into .xinitrc and started X.org with startx. In cwm used Alt+Shift+Enter to start xterm.
Following https://flathub.org/en/setup/Debian I have added flathub repository: flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
I ran the command as the non-root user, it asked for the root password and I entered it. Then I ran flathub install flathub chat.delta.desktop, again entered the root password when it asked.
Then started Delta Chat with flathub run chat.delta.desktop.
Created a new profile, tried to export a backup, and it failed with “Error code 3850” in the log.
In the log I noticed the line: “src/imex.rs:158: Export path: /run/user/1000/doc/613104b2/user”
On my system where exporting works, I have this in the log:
src/imex.rs:158: Export path: /run/user/1000/doc/EEenso35vM1FB3c2qETrFg/user
src/imex.rs:460: Backup '/home/user/.var/app/chat.delta.desktop/config/DeltaChat/accounts/b0127be9-bf09-4ae8-b252-791256dc6132/dc.db' to '/run/user/1000/doc/EEenso35vM1FB3c2qETrFg/user/delta-chat-backup-2026-09-19-00-bn14kdyur@nine.testrun.org.tar'.
I tried to attach the database manually on my system, it worked:
$ sqlite3 /home/user/.var/app/chat.delta.desktop/config/DeltaChat/accounts/b0127be9-bf09-4ae8-b252-791256dc6132/dc.db
SQLite version 3.53.4 2026-07-24 19:02:57
Enter ".help" for usage hints.
sqlite> ATTACH '/run/user/1000/doc/EEenso35vM1FB3c2qETrFg/user/foo.db' AS backup;
mount showed this:
portal on /run/user/1000/doc type fuse.portal (rw,nosuid,nodev,relatime,user_id=1000,group_id=1000)
On Debian 12 I installed sqlite3 with apt install sqlite3 and tried the same thing: went to ~/.var/app/chat.delta.desktop/config/DeltaChat/accounts/30e86195-f23a-45e6-b1fa-1ecc7c2170f5 and ran sqlite3 dc.db.
Trying to attach failed:
$ sqlite3 dc.db
SQLite version 3.40.1 2022-12-28 14:03:47
Enter ".help" for usage hints.
sqlite> ATTACH DATABASE '/run/user/1000/doc/613104b2/user/backup.db' AS backp;
Runtime error: disk I/O error (10)
sqlite>
I ran SQLite under strace (strace sqlite3 ~/.var/app/..., pressed “up” arrow to select previous command) and it failed with
Implement getlk and setlk, and honour O_NOFOLLOW, in the Document portal’s FUSE filesystem.
On my system where exporting backup works, xdg-desktop-portal is version 1.22.1. On Debian 12 xdg-desktop-portal is version 1.16.0-2 according to apt show xdg-desktop-portal.
Debian 13 (trixie, stable) has xdg-desktop-portal 1.20.3+ds-1.
To try the new version, I edited /etc/apt/sources.list to replace “bookworm” with “trixie” everywhere (%s/bookworm/trixie/g in vi). Ran apt update and then apt install xdg-desktop-portal to upgrade. This is not a proper way to upgrade bookworm to trixie. Should have upgraded properly, it anyway pulled new version of libc etc., basically upgraded almost everything. Anyway, after upgrading I stopped everything with killall cwm, ran startx again, started Delta Chat and backup export succeeded, I got a .tar file.
Thank you for the investigation! Would you be able to provide some intuition for why this error shows up when exporting the database and not when using the sqlite database during normal use?
I am also curious about the benefits of this sqlite-specific operation compared to the generic operations used e.g. to export attachments to the Downloads folder. After all the procedure ian suggested to manually create a backup file used generic file operations and no sqlite3 commands.
Normal SQLite database is in ~/.var/app/..., it is likely also locked, but locking works there because it is a normal ext4 filesystem. When exporting a database for backup, we create a new database in /run/user/1000/doc which is a FUSE filesystem implemented by xdg-desktop-portal.
Exporting a backup with SQLite commands makes sure that WAL (write-ahead log) is also included in the database. If you copy the database manually, but don’t keep the WAL, you may lose some changes, e.g. some message may be missing or even restored (if deletion was written in the WAL, but not snapshotted yet. Also if you copy the database while it is changed e.g. by copying the database file byte-by-byte while Delta Chat writes into it, I don’t know what can happen, maybe you can end up with a corrupted database.
Locking of the target database might be unnecessary if you are absolutely sure that nobody will try to open it at the same time, but SQLite always locks databases when writing into them and I think it’s correct that it expects that locking works.
thanks, that makes sense. it’s just too bad that it breaks without warning on platforms that will still be supported for years to come – Debian 12, Ubuntu 24.04, AlmaLinux 9, etc. flatpaks are often billed as a way to get more up-to-date software without the need to upgrade a stable system, so it’s unfortunate if the only recourse in this case is to upgrade.
I guess people can use the workaround I found, but the ability to export a backup is also useful on its own rather than just to add a second device. can you see any reasonable way to avoid this dependency? maybe write a copy of the database to a temporary file under ~/var, then copy it to the FUSE filesystem?
when I get the chance I will take another crack at ian’s suggested workaround, since I was having problems on both the sender side and the recipient side.
I have looked into creating temporary files in the OS temp_dir, but then the problem is that on Android this is a cache directory that will not be cleaned up, so if backup fails, you might end up with the database copy stored there. Creating temporary files next to the exported backup has the advantage that user can clean up anything that ends up there on failure, while on mobile OSes there may be no temp dir and “temporary” files end up in inaccessible directories.
Maybe we can create a “temporary” directory in the data folder, and just clean up whatever is there on every app start.
I found it the hard way that SQlite also tries to lock and write to the database even if you open it readonly and in safe mode, so it can fail on a read-only file system or with restrictive permissions.
One problem with creating temporaries in the data folder is if your profile already takes up many gigabytes, the partition might not have sufficient space to store it twice or three times.