The simplest cause is that the entire
/run/user/<UID> directory does not exist – it hasn't been created by systemd-logind, typically because the UID in question hasn't gone through the standard "user login" procedures, but was merely
sudo'd to, without invoking pam_systemd.
("Permission denied" comes from dconf's attempting to mkdir all the parent directories, which it cannot do because /run and /run/user themselves are only writable by root.)
This directory is created when at least one session for that UID is created – and similarly, it will be deleted when systemd-logind sees a user's session count drop to 0. For example, in one of your posts, using
su -l instead of
su may solve the problem because it makes su use a different PAM configuration, one where pam_systemd is enabled.
So if the error message begins showing up for your own UID while using your desktop via VNC, then it likely means that the entirety of the VNC process tree exists outside of any systemd-logind "session" (i.e. PAM wasn't used while starting the VNC server) and therefore isn't part of the reference-count that would prevent systemd-logind from deleting the
/run/user/<UID> directory upon logout.
(For example, if you connect to a remote host via SSH, the user runtime directory is created; then you start something like "vncserver.service" and everything seems fine; but as soon as you disconnect from SSH, the runtime directory is deleted again because that was your last session.)
(You can see this in
journalctl, possibly indirectly – the runtime directory is created/deleted at the same time when the "systemd --user" instance, named "User Manager for UID <UID>", is started/stopped.)
In those situations, one way to make the runtime directory "permanent" is to set systemd-logind's linger flag for that user, using
loginctl enable-linger <USERNAME>. This will cause that user's runtime directory (and their
systemd --user instance) to be started on boot and kept around until shutdown.
Alternatively, if VNC is being started via systemd, its .service's
PAMName= parameter should be used to create a full PAM session which will register with systemd-logind and will cause the runtime directory to be created as long as the VNC .service is running.
A second related cause is that dconf is being told to use another user's runtime directory. The "/run/user/<UID>" pattern isn't determined by dconf directly – instead the whole path is taken from your
XDG_RUNTIME_DIR environment variable that's set by PAM.
If you use something like
sudo -E to run graphical programs as a different user, they will inherit all of your environment – they might be able to live with your $HOME if it is world-readable, but they will not be able to use your $XDG_RUNTIME_DIR as it is only accessible by you (by design).
The solution is "don't do that", i.e. don't make programs run under other UIDs inherit your $XDG_RUNTIME_DIR and related environment. Specifically for dconf, it will fall back to the user's ~/.cache/dconf if it needs to (although this assumes it didn't inherit the wrong $HOME, either).