UniClipboard

Troubleshooting

Triage path for sync, pairing, clipboard permissions, log collection, and emergency reset.

Edit on GitHub

UniClipboard issues fall into a small set of layers: is the daemon running → is pairing established → can the peer be discovered → does transport work → did the representation land. Walk them in that order. Each section below tells you which signals to look at and which commands to run.

Before guessing, run uniclip status and uniclip members on both ends. The "should be online" feeling rarely matches what's actually on the wire.

Start here: 30-second triage

SymptomMost likely layerJump to
Command says "daemon not running"DaemonDaemon
join <code> errors out or hangsPairingPairing failures
Both online but members doesn't list each otherDiscoveryPeer not appearing
Peer is visible but sync is slow / files stallTransportStuck on relay / slow sync
You copy something and the peer gets nothingClipboard permissionClipboard permissions
Search returns nothing or "index not ready"Full-text indexSearch & index
Phone can't reach the desktop / 401 / corrupt imageMobile syncMobile sync (iOS Shortcut)

Daemon

Every CLI sync command depends on the daemon. Use uniclip start to launch, uniclip stop to shut it down, and uniclip status to inspect health.

uniclip status            # summary
uniclip status --json     # stable fields, easy to diff

Key fields:

  • daemon.running — whether the process is alive.
  • space.bound — whether the current profile is bound to a space. false means you haven't init-ed or join-ed yet.
  • network.endpoint — this device's iroh node ID. Switching Wi-Fi doesn't change it; if it changes, you switched profile or keyslot.
  • network.relay — relay domain in use; null means direct.
  • peers[].reachability — per-peer reachability snapshot.
  • membership_convergence — whether the active space is fully connected: complete, converging, waiting_for_upgrade, or blocked.

If daemon.running = false but uniclip start exits immediately, run it in the foreground to capture the trace:

uniclip start --foreground -v

A common cause is the keyslot file being held by another process — typically the GUI and uniclip racing on the default profile. Adding --profile dev on the CLI side keeps them out of each other's way.

Daemon log shows "System secure storage probe failed; falling back to file-based KEK"

This WARN means the daemon could not reach the freedesktop Secret Service (GNOME Keyring / KWallet) at startup. The daemon still starts; the Key Encryption Key is just written to disk under the app's data directory instead of into the system keyring. Two situations commonly trigger it:

Snap sandbox — AppArmor refused the D-Bus call because the password-manager-service plug is not connected. Reconnect it to move the KEK back into the system keyring:

sudo snap connect uniclipboard:password-manager-service
# then restart the app

Minimal Wayland session (hyprland / sway, etc.) — the session looks like a desktop (DISPLAY and DBUS_SESSION_BUS_ADDRESS are set), so the daemon tries the system keyring, but no secret service is running — or one is running but locked with no prompter to unlock it. The probe is bounded by a short timeout, so the daemon degrades to file-based KEK after a few seconds instead of hanging. To keep using the system keyring, run an unlocked secret service in the session, for example:

gnome-keyring-daemon --start --components=secrets
# better: unlock it automatically at login via pam_gnome_keyring,
# or enable KeePassXC's "Secret Service Integration"

On older revisions the same situation could hang or crash daemon bootstrap with Daemon startup/probe failed during Tauri bootstrap. Current revisions degrade to file-based KEK instead; reconnecting the snap plug or starting a secret service then only affects where the KEK is stored, not whether the daemon starts.

Pairing failures

Invite says "invalid or expired"

Invitation codes are short-lived and single-use. Once consumed or expired, regenerate one on the sponsor:

uniclip invite        # issue a fresh one on the sponsor

Don't treat invites like long-lived credentials or paste them into a chat history — they're designed to live only until the next handshake.

Correct invite, but the handshake hangs

The handshake runs PAKE to verify the passphrase. If the peer never appears in members:

  1. Confirm clocks on both ends agree to within a few minutes. Argon2id and signature checks are sensitive to clock drift.

  2. On the sponsor, uniclip status --json | grep handshake shows whether it's waiting for a joiner. If nothing arrived, discovery itself is broken — jump to Peer not appearing.

  3. The default handshake TTL is roughly three minutes. After that the sponsor drops the invite and the joiner sees "invitation expired". Just invite again.

  4. Sponsor running Tailscale or a similar overlay? By default, Tailscale CGNAT (100.64.0.0/10) and IPv6 ULA (fd7a:115c:a1e0::/48) addresses are stripped from the invitation, so the joiner only sees unreachable LAN addresses and dial attempts hang. On the sponsor, enable Settings → Network → Allow overlay network addrs and restart the daemon so Tailscale addresses get included. Clash TUN fake-ip (198.18.0.0/15) and IPv4 link-local (169.254.0.0/16) are always filtered with no opt-out — those interfaces aren't real dial targets, so leave UniClipboard on a physical NIC instead.

    This toggle only affects desktop ↔ desktop pairing. Mobile sync has its own Bind IP dropdown (Configure modal / device-card dialog), which always lists Tailscale CGNAT interfaces regardless of Allow overlay network addrs — mobile pairing is a manual pick, so a Tailscale-reachable phone can be paired even with the toggle off.

"passphrase mismatch" or kicked right after joining

Wrong passphrase makes the key rewrap fail. This is by design — the sponsor never sees the bad passphrase in plaintext. Double-check and retry.

A lost passphrase is unrecoverable. That's the price of Argon2id + PAKE: there's no copy on any server that could decrypt anything. If you still have access on another device, revoke the lost one (or rebuild the space) from there.

Peer not appearing

Discovery runs three lookups in parallel: mDNS, rendezvous, cached direct addresses. Any hit wins. If the peer never shows up in members:

Same Wi-Fi? Rule out AP isolation

Many home routers and café Wi-Fis enable client / AP isolation by default, which drops mDNS and unicast traffic between devices on the same SSID.

  • Look for "AP Isolation", "Client Isolation", or "Wireless Isolation" in the router admin and turn it off.
  • Guest networks usually leave isolation on permanently — move both devices to the main network.

Different networks? Confirm rendezvous reachability

Cross-network discovery depends on rendezvous over HTTPS. On strict corporate networks an inspecting middlebox may break HTTPS egress entirely.

  • Switch one device to a phone hotspot and retry. If it works there, the original network's egress policy is the culprit.
  • Firewall allowlists need to permit iroh's default rendezvous and relay domains. Inspect uniclip status --json (network field) for the exact hosts in use.

Clock drift?

Signed address records carry timestamps. If one end's clock drifts more than a few minutes, the other side rejects its records as expired — producing the "looks online, can't find each other" pattern.

Stuck on relay / slow sync

A non-empty network.relay in uniclip status means the path is relayed — it works, but with worse latency and bandwidth than direct. If both devices are on the same network and you still see relay use:

  • Symmetric NAT. Some carriers and mobile networks allocate ports unpredictably, breaking hole-punching. Switching networks (or enabling IPv6) usually fixes it.
  • IPv6 disabled along the path. Direct fails over to IPv4 NAT punching, which is more fragile.
  • Corporate networks. Locked-down outbound UDP forces relay use, and some of these networks block the relay too — in which case UniClipboard simply isn't usable on that network.
  • A local proxy is intercepting relay traffic. Overseas relay + a local proxy (Clash / Surge / etc.) on the same machine usually means the proxy is also forwarding relay traffic, bottlenecking bandwidth at the proxy egress and degrading UDP/QUIC. Route the relay domain to DIRECT — see Self-host an iroh relay — Direct-connect the relay if you also run a local proxy.

The relay only ever sees ciphertext. Its availability affects performance and reachability, not confidentiality. See Pairing & sync — Transport.

File-class payloads use a chunked blob protocol (see What syncs — Large payloads), which resumes after disconnects and wake-from-sleep. If a single big file has been creeping along for hours at near-zero rate, a chunk is probably stuck without retrying. On the sender, uniclip stop && uniclip start usually unsticks it.

Clipboard permissions

If a copy produces nothing on the peer, and uniclip watch shows no event either, the local side likely never read the clipboard.

The recorded global Quick Panel hotkey requires Input Monitoring. Grant it in System Settings → Privacy & Security → Input Monitoring, then fully quit and relaunch the app.

The optional modifier double-tap trigger uses a separate Accessibility grant. UniClipboard checks this permission silently and keeps the selector disabled until it is available. Click Open Accessibility settings beside the selector; if UniClipboard is not listed, click + and add /Applications/UniClipboard.app. Return to the app after granting access. Clipboard capture itself does not require Accessibility.

Windows usually needs no extra grants. If uniclip watch is silent:

  • Antivirus or EDR may be blocking the clipboard hook in UniClipboard.exe / uniclip.exe. Check the event log or the AV quarantine.
  • Inside an RDP session, the clipboard is separate from the host. Turn off RDP clipboard redirection and retry.

The desktop session matters more than the distro:

  • Wayland: ext-data-control-v1 (GNOME / mutter ≥ 47, Plasma 6) and wlr-data-control (Sway / Hyprland and other wlroots compositors) are supported natively — no bridge tooling required. When neither protocol is available, capture falls back to XWayland (the X11 path) automatically.
  • X11: works out of the box with the built-in native clipboard listener; no external clipboard tools (xclip / xsel) are needed.
  • Headless servers: with no X / Wayland, only the CLI's send / watch features work; GUI clipboard capture isn't available.

Search & index

uniclip search status reports the full-text index state.

uniclip search status      # ready / building / missing
uniclip search rebuild     # synchronous rebuild (blocks until done)

Common cases:

  • "index not ready" — daemon just started or post-upgrade rebuild in progress. status reports progress.
  • Old entries missing after rebuild — they may have been GC'd by the retention policy during upgrade. The hidden command uniclip dev dump-clipboard --limit N lets you confirm whether they're still in history at all.
  • Corrupt index file (rare) — usually after a SIGKILL during writes. Delete the index subdirectory under the data folder, then uniclip search rebuild. The clipboard history itself lives in a separate file and isn't affected.

Mobile sync (iOS Shortcut)

The mobile companion runs over plain HTTP with Basic Auth (TLS comes from a reverse proxy) — completely separate from the iroh peer mesh. Most failures fall into one of these buckets.

Phone can't open the URL

Symptom: tapping the install URL or running the Shortcut times out without ever showing a 401 / 4xx response.

  1. Can the phone reach the address you advertised? In the default setup the phone and desktop must be on the same Wi-Fi / subnet; if you're using a server node (public HTTPS) or Tailscale / VPN, make sure the phone is going through that channel. Mobile sync itself has no relay and no NAT punching.
  2. The advertised IP must be reachable from the phone. The desktop socket always binds to 0.0.0.0, but the URL baked into the install link must be a real LAN IPv4 the phone can dial. The Configure dialog enforces this: with Bind IP on Auto, the "Current listening address" row expands inline into every RFC1918 candidate — copy the one the phone is on; with a specific interface picked, the row shows that single fixed URL. From the CLI, pass --ip <LAN_IPV4> to uniclip mobile network set.
  3. Check listener state. uniclip mobile status reports lan_listener_error if the daemon tried to bind and failed (port in use, permission denied). Resolve the underlying error or pick a different port.
  4. Firewall on the desktop OS. Confirm inbound traffic on port 42720 (or your custom port) is allowed for the LAN profile.
  5. Did you change the IP / port recently? A daemon restart is required to apply listener changes; the Shortcut on the phone also needs its url field updated to match.

401 Unauthorized

The username or password is wrong. Reasons:

  • The plaintext password is shown once at registration. If you lost it, click Rotate password on the device row (or uniclip mobile revoke <id> + add) — there is no way to recover the original.
  • The Shortcut on the phone may still hold an old credential after rotation. Re-edit the url / username / password fields.

Image from iPhone arrives broken / not visible

The desktop sniffs the magic bytes of incoming uploads to recover the correct image/* MIME (iOS Shortcuts often sends application/octet-stream regardless of file extension). The sniffer landed in 0.7.0-alpha.6; if JPEG / PNG uploads render as blank or invalid pasteboard images, confirm with uniclip --version and upgrade to 0.7.0-alpha.6 or newer.

Public Wi-Fi

Don't run the LAN listener on coffee shop / airport / conference Wi-Fi. The v1 wire format is plain HTTP with Basic Auth — anyone on the same SSID can sniff your clipboard. If you need to use it on an untrusted network, set the listener to disabled first (uniclip mobile network off) and re-enable on a trusted network.

Changed the LAN IP / port?

Two things have to happen for the new value to be live:

  1. Restart the daemon so the listener rebinds.
  2. Update the Shortcut's url field on the phone to match the new advertised URL.

uniclip mobile status is a fast way to confirm what the daemon is currently advertising.

Collecting logs

The fastest way to gather everything for an issue report is the built-in export, which zips the GUI, daemon, and CLI logs from the last 24 hours into your Downloads folder:

  • GUI: Settings → General → Export logs.
  • CLI: uniclip debug export-logs (use --since-hours <N> to widen or narrow the window).

If a problem is hard to reproduce, enable verbose logging first (Settings → General → Debug mode, or uniclip debug on), reproduce, then export. Turn it back off and restart afterwards.

If you'd rather grab the files by hand, logs live in each platform's conventional log location (separate from the encrypted history). Only the last 7 days are kept per process; older files are removed automatically:

PlatformPath
macOS~/Library/Logs/app.uniclipboard.desktop/
Linux~/.local/state/app.uniclipboard.desktop/logs/
Windows%LOCALAPPDATA%\app.uniclipboard.desktop\logs\

On Linux, if the state directory is unavailable, logs fall back to the data-local root instead: ~/.local/share/app.uniclipboard.desktop/logs/.

Each process writes its own file: uniclipboard-gui, uniclipboard-daemon, or uniclipboard-cli. With UC_PROFILE set, the directory carries a suffix (app.uniclipboard.desktop-dev). See Install — Where data lives.

Reproduce while capturing — much better than digging through old logs:

# Run the daemon in foreground with debug-level output piped to the terminal
uniclip stop
uniclip start --foreground -v

When filing an issue, please attach:

  • uniclip --version, OS and version.
  • uniclip status --json from each end.
  • Repro steps with timestamps; the log slice covering that window is enough — no need to upload the full file.
  • Don't paste database files, invitation codes, or space passphrases into the issue.

Emergency reset (last resort)

The operations below destroy local clipboard history and can't be rolled back. Use them only after the steps above failed.

If the app gets you all the way to the unlock screen (passphrase prompt) but you can't recall the passphrase, you don't need the CLI:

  1. On the unlock screen, click Forgot passphrase? Reset and start over. The link sits at the bottom of the page and is also exposed inside the passphrase modal.
  2. Type RESET in the confirmation dialog and press Reset.
  3. The app deletes the on-disk keyslot and KEK on this device, clears SetupStatus, and drops you back at the setup screen. From there init a fresh space or join from another device.

This is the same destructive operation as the CLI tabs below — local history on this device is unrecoverable afterwards. Other devices in the space are unaffected (see the warning below).

uniclip stop
# Then delete the profile's data directory (path above).
# Linux example:
rm -rf ~/.local/share/app.uniclipboard.desktop

After cleanup, uniclip init or uniclip join starts fresh. The keyring's KEK entry will be overwritten by the next init.

  1. Quit the GUI; uniclip stop.
  2. Uninstall the package:
    • macOS Homebrew: brew uninstall --cask uniclipboard && brew uninstall uniclipboard
    • Windows: Settings → Apps → UniClipboard → Uninstall (or Control Panel → Programs & Features)
    • Linux Snap: sudo snap remove uniclipboard
    • Linux COPR (dnf): sudo dnf remove uniclipboard && sudo dnf copr disable mkdir700/uniclipboard-alpha
    • Linux .deb: sudo apt remove uniclipboard
    • Linux .rpm (one-shot install): sudo dnf remove uniclipboard
    • AppImage: delete the .AppImage file.
  3. Delete the data directory (paths above).
  4. Manually clean keyring entries:
    • macOS Keychain: search uniclipboard, delete entries.
    • Windows Credential Manager: Control Panel → User Accounts → Credential Manager → Windows Credentials, remove uniclipboard:*.
    • Linux Secret Service: use seahorse or secret-tool to wipe the uniclipboard namespace.

Resetting one device does not revoke it on the other devices in the space. To make a device disappear from the space, revoke it from another online device — clearing local data alone does not invalidate its node ID's trusted status.

Still stuck?

  • Skim the FAQ — many "issues" turn out to be intentional behavior, not bugs.
  • If something is genuinely off, file an issue at github.com/UniClipboard/UniClipboard/issues. Follow the log collection checklist above.
  • For security issues, use the private disclosure channel listed in SECURITY.mddon't open a public issue.

On this page