On this page
OptimizationDiagnostics

Troubleshooting & Diagnostics

Diagnosing display capture, PipeWire audio routing, controller mappings, and GPU encoding issues.

7 min readUpdated August 2026

Quick Diagnostic Checklist#

When encountering streaming issues, follow this verification flow:

  1. Check Logs: Open https://localhost:47990/logs or run journalctl --user -u app-dev.lizardbyte.app.Sunshine.service -n 100.
  2. Check Port Bindings: Verify UDP 47998-48010 and TCP 47984/47990 are listening (ss -tulwn | grep -E "4798|4799|4800|4801").
  3. Inspect Subsystem Errors: Query /api/errors to check if encoder or capture counters are incrementing.
SolarFlare Web UI troubleshooting page
The Troubleshooting tab surfaces logs and recent errors in the Web UI.

Capture, audio, and network diagnostics#

Pick the symptom tab that matches the Moonlight overlay or host logs.

Confirm capture backend (kms, portal, x11). KMS needs cap_sys_admin. NVIDIA needs nvidia_drm.modeset=1. KWin overlays can break KMS on Plasma 6.5+ (KWIN_USE_OVERLAYS=0).

bash
getcap "$(command -v sunshine)"
journalctl --user -u app-dev.lizardbyte.app.Sunshine.service -n 80 --no-pager

PipeWire & Audio Sink Diagnostics#

SolarFlare connects to PipeWire directly.

  • If no audio is received on client: Open pavucontrol or qpwgraph while streaming. Verify that the SolarFlare capture stream is linked to your default audio sink monitor.
  • If audio crackles: Increase pipewire_latency_ms from 1 or 4 up to 8 or 12 ms.

Black screen by capture backend#

SolarFlare has six capture paths and each fails differently. Identify yours first, then apply the matching fix:

bash
getcap "$(command -v sunshine)"
ls -l /dev/dri/card* /dev/dri/render*
echo "$XDG_SESSION_TYPE $WAYLAND_DISPLAY $DISPLAY"
cat /sys/module/nvidia_drm/parameters/modeset
grep -E "^capture =|^adapter_name|^output_name" ~/.config/sunshine/sunshine.conf
journalctl --user -u app-dev.lizardbyte.app.Sunshine.service -n 80 --no-pager | grep -iE "kms|capture|portal|wayland|x11|hermes|Probably not permitted"
BackendFailure signatureFix
KMSProbably not permitted on /dev/drisetcap cap_sys_admin,cap_sys_nice+p; user in video group; re-login
KMS NVIDIANo modes / modeset Nnvidia_drm.modeset=1 kernel param, reboot
WaylandMissing output metadataskip_wayland_correlation = true only as last resort (breaks absolute mouse)
Portalportal session closedCheck xdg-desktop-portal running; re-accept the share dialog
X11No displays / wrong screenDISPLAY=:0 set; xrandr --listmonitors; VIRTUAL1 or headless_mode
Hermes-KMSModule absentInstall headers + DKMS module; look for HERMES-1 source
Plasma 6.5+Flicker with overlaysKWIN_USE_OVERLAYS=0

Encoder failures by vendor#

When logs say no working encoder was found, check the vendor stack directly. HDR fallbacks (hevc/av1 modes 3+) silently downgrade when the chain is not 10-bit end to end.

bash
vainfo; vainfo --display drm --device /dev/dri/renderD128
nvidia-smi --query-gpu=name,driver_version --format=csv
lspci | grep -E 'VGA|3D'; ls -l /dev/dri/render*
journalctl --user -u app-dev.lizardbyte.app.Sunshine.service -n 200 --no-pager | grep -iE "encoder|nvenc|vaapi|qsv|vulkan|sw_preset|not supported"

Pairing & discovery failures#

PIN failures are usually time skew, firewall asymmetry, or origin policy — not the PIN itself. Host and client clocks must agree within ~30 s. mDNS needs one broadcast domain with no AP isolation; otherwise add the host by LAN IP.

bash
timedatectl status
ss -tlnp | grep -E '47984|47990|48010'; ss -ulnp | grep -E '47998|48000'
curl -sk https://127.0.0.1:47990/api/health | jq .
grep -E "trusted_subnets|trusted_subnet_auto_pairing|origin_web_ui_allowed|const_pin|upnp|^port =" ~/.config/sunshine/sunshine.conf
journalctl --user -u app-dev.lizardbyte.app.Sunshine.service -n 100 --no-pager | grep -iE "pair|pin|cert|crypto|origin"

Web UI 401 / 403 / CSRF errors#

401 means no or bad credentials; 403 means scope, origin policy, or CSRF. Browser cross-origin POSTs need X-CSRF-Token from GET /api/csrf-token (1 h TTL); curl without Origin/Referer is exempt. Ten login failures per IP per 30 s triggers 429. Forgotten passwords reset with sunshine --creds followed by a service restart.

bash
curl -vk https://localhost:47990/api/config -w "%{http_code}"
CSRF=$(curl -sk -u "$USER:$PASS" https://localhost:47990/api/csrf-token | jq -r .csrf_token)
grep -E "csrf_allowed_origins|origin_web_ui_allowed|api_tokens" ~/.config/sunshine/sunshine.conf
sunshine --creds "$USER" "$PASS"; systemctl --user restart app-dev.lizardbyte.app.Sunshine.service

Logs, error counters & telemetry#

Error counters (encoder, capture, network, session, process, config, crypto, unknown, total) are monotonic since start — diff the total over 60 s and want zero deltas. min_log_level accepts verbose, debug, info, warning, error, fatal. Never run two instances: stop the user service before a foreground repro.

bash
curl -sk -H "Authorization: Bearer $TOK" https://localhost:47990/api/errors | jq .
curl -sk -H "Authorization: Bearer $TOK" https://localhost:47990/api/logs | tail -100
SUNSHINE_LOG_JSON=1 systemctl --user restart app-dev.lizardbyte.app.Sunshine.service
journalctl --user -u app-dev.lizardbyte.app.Sunshine.service -p err -b -n 100 --no-pager

Self-update failures#

Updater phases: idle, checking, downloading, verifying, ready, waiting_idle, applying, restarting, error, unsupported (non-Linux). A non-empty session list blocks apply unless when_idle is false. SHA256SUMS mismatches, missing pkexec/helper, and lost setcap after binary swap are the common causes.

bash
curl -sk -H "Authorization: Bearer $TOK" https://localhost:47990/api/update | jq '{phase,message,percent,busy,can_apply,latest_tag,outdated}'
curl -sk -H "Authorization: Bearer $TOK" https://localhost:47990/api/sessions | jq .
journalctl --user -u app-dev.lizardbyte.app.Sunshine.service --no-pager | grep -iE "update|staging|SHA-256|tarball|setcap|pkexec|helper"