Troubleshooting

Troubleshooting Guide

This page reflects the current desktop/mobile architecture in v0.1.1.

Before You Debug

Start by deciding which surface is actually failing:

  • desktop hub
  • iPhone companion
  • remote route
  • buyer/download/license flow

Connectivity

Mobile or remote client gets 401 Unauthorized

This usually means the client is trying to use protected /api/* routes without a valid bearer token.

What to do:

  1. Re-open the latest desktop QR instead of reusing an old remote URL.
  2. If the desktop shows pairing_not_armed, arm pairing again before reconnecting.
  3. On mobile, disconnect and reconnect so the app can pair again or refresh auth state.

Remote playback fails with a license-related message

This is different from a normal network error.

What to check:

  1. The desktop hub has an active license state for remote access.
  2. The hub can still validate or reuse its signed entitlement state.
  3. You are not testing remote while expecting LAN-only behavior.

QR returns 409 pairing_not_armed

This is expected when a remote route exists but the desktop has not armed pairing yet.

What to do:

  1. Open the desktop app locally.
  2. Arm pairing from the remote/connect settings flow.
  3. Refresh the QR and rescan it.

Files or /api/browse returns 401, 403, or Forbidden

The folder browser is a protected route for remote callers.

What to do:

  1. Make sure the client is paired and has a fresh bearer token.
  2. Reconnect from the QR if the auth state is stale.
  3. Confirm the folder still exists on disk.

If the phone was already paired and public web access is set to Shared pages only, /api/browse should still work for that paired phone. A new 403 there usually means the mobile private-access path regressed, not that the remote route itself is missing.

Mobile cannot reach the hub locally

What to check:

  1. The desktop hub is running on 38472.
  2. Both devices are on the same network if you are not using Cloudflare or Tailscale.
  3. The desktop host is reachable at YOUR_IP:38472.
  4. Firewall rules are not blocking the app.

Helpful local checks:

curl http://localhost:38472/api/ping
lsof -i :38472

Database health

Desktop opens but library/settings look unavailable

The hub may be in degraded mode because the DB is faulted or incompatible.

Check:

curl http://localhost:38472/api/info
curl http://localhost:38472/api/settings

Look for databaseHealth.status.

Recover a faulted DB

Use the local rebuild flow instead of deleting the DB by hand.

curl -X POST http://localhost:38472/api/database/rebuild

Notes:

  • this route is local-only
  • the old DB is preserved and archived before replacement
  • a full rescan may start automatically afterwards

Database path and logs

Current default locations:

  • DB: ~/.music-hub/music.db
  • Config: ~/.music-hub/config.json
  • Electron log: ~/.music-hub/electron.log

Playback

Public share page loads but playback fails

Public share pages depend on bootstrap + signed media sessions.

What to check:

  1. The share bootstrap endpoint returns 200.
  2. Reloading the same link in the same browser tab should reuse the same shareSessionId instead of creating a new one.
  3. The share page is still renewing shareSessionId with /api/share/session/heartbeat.
  4. The media request includes the latest mediaToken.

If too many interactive share sessions are active at once for the same page, the server can return 429. Preview bots from WhatsApp, Telegram, Discord, etc. should appear in session telemetry but should not consume that interactive limit.

Playback is slow or stutters

What to check:

  1. Prefer a strong Wi-Fi signal or a closer route to the hub.
  2. If remote, confirm the client is not repeatedly falling back after direct-stream failures.
  3. Restart the current playback session if a stale connection mode was cached.

Remote access

Web session bootstrap failed (403) in the browser (full hub, not /share/)

That message comes from the desktop UI calling POST /api/auth/web-session before protected API calls when the page is loaded on a non-localhost hostname (for example your Cloudflare URL).

Checklist:

  1. allowRemoteOpenAccess in config — After toggling Public remote URI in Advanced, confirm ~/.music-hub/config.json has "allowRemoteOpenAccess": true. If it stays false, the setting did not save (wrong hub process, or the request failed).

  2. License / remote entitlement — If the hub is not remoteLicensed, the server returns 403 with code: license_required_for_remote (not browser_access_disabled). Fix license/validation first.

  3. Same machine behind the tunnel — The browser must hit the same desktop instance that you configured.

  4. Proxy headers — The hub classifies traffic using forwarded client IP headers (cf-connecting-ip, x-forwarded-for, etc.). If your edge strips them, anonymous browser access rules may not apply as expected.

Public /share/... pages use a separate path: they should load shared content without opening the full hub and without requiring Public remote URI (see share bootstrap in the API docs). If only share pages fail, check the share bootstrap response and license, not only web-session.

Cloudflare/Tailscale route exists but app still cannot browse library

Remote networking alone is not enough anymore. The client still needs auth.

What to check:

  1. Pair/refresh flow succeeded.
  2. The remote client is sending Authorization: Bearer ....
  3. You are not trying to call a local-only endpoint remotely.

Phone was paired on Wi-Fi, Wi-Fi is now off, and covers/search/playback all die together

That path should now work without a re-pair if the phone was already paired once.

What to check:

  1. The phone is using the latest saved hub config or link from desktop.
  2. The paired bearer can still reach /api/media/session, /api/search, and /api/browse.
  3. The desktop remote scope is only limiting public web access, not the phone's private session.
  4. The mobile diagnostics log does not show repeated Protected request failed or Remote media session failed.

Share page assets fail behind a custom proxy

Music Hub expects the share page and its static assets to load same-origin, while API CORS stays narrow.

If you front the app with your own proxy:

  1. Pass /share/* and static assets through without rewriting them into API requests.
  2. Do not force unknown origins to throw inside API CORS handling.

Mobile iOS shipping

EAS prompts to run git init even though mobile/ is already a git repo

This often happens when Git refuses the repository with dubious ownership (the folder is owned by a different user UID than the account running the build). EAS then assumes there is no usable git metadata.

What to do:

  1. Prefer fixing ownership: sudo chown -R "$(whoami)" /path/to/mobile (adjust path).
  2. Or allow the path explicitly: git config --global --add safe.directory "/absolute/path/to/mobile".
  3. Re-run npm run build:final from mobile/.

The mobile build scripts also attempt to register safe.directory automatically before invoking EAS when they detect this pattern.

Packaging and startup

macOS app is blocked on first open

Because the app is still in beta distribution:

  1. Right-click the app and choose Open.
  2. If macOS blocks it, allow it in Privacy & Security.

Splash screen stays visible too long

Check the Electron log first:

tail -f ~/.music-hub/electron.log

If the backend is healthy but the UI is not loading, also test:

curl http://localhost:38472/api/ping
curl http://localhost:38472/api/settings

Buyer / Recovery Flow

I paid, but I lost the original email

Use the current recovery path exposed from the landing flow instead of expecting a permanent raw DMG URL.

The download link expired

That is expected for the current secure download flow. Use the recovery flow to generate a fresh short-lived download link.