From 09f6cf8c0f4e09536a6dec955f1d1d7ea27661ef Mon Sep 17 00:00:00 2001 From: Duncan Tourolle Date: Mon, 17 Aug 2026 14:21:00 +0200 Subject: [PATCH] Name the sidecar the drain could not deliver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The write path learned to say which file the server refused; the drain path — the one that runs for work queued while offline — still reported only a count. That is the path that matters most, because everything it carries was made with no connection and exists on one device. With it named, the failure on the tablet is: draining PhotosRaw/2026/2026-08-03/_MG_9221.drsc: permission denied on a credential that pushes the catalog to the same library root in the same pass. So this is not the account and not the app password: one path is writable and another is not, which points at the server — a read-only share over that folder, or a file access control rule on the extension — rather than at anything this side can retry its way out of. Co-Authored-By: Claude Opus 5 --- ui/dr-ui/src/library.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ui/dr-ui/src/library.rs b/ui/dr-ui/src/library.rs index d23b0d5..5428e67 100644 --- a/ui/dr-ui/src/library.rs +++ b/ui/dr-ui/src/library.rs @@ -698,7 +698,10 @@ pub fn spawn_outbox_drain( match drain_one(&backend, &cache, path_str).await { Ok(()) => report.written += 1, Err(e) => { - log::debug!("draining {path_str}: {e}"); + // Warn, for the reason the write path does: this is + // unsynced work and the path is what makes the failure + // actionable. + log::warn!("draining {path_str}: {e}"); report.last_error = Some(e); report.failed += 1; // Still queued — the marker was never cleared.