Troubleshooting¶
Connection Issues¶
"Radio did not respond to discovery"¶
Symptom: TimeoutError: Radio did not respond to discovery after 10 attempts
Causes:
- Wrong IP address — verify your radio's IP in its network settings menu
- Radio not on network — ensure the radio is powered on and connected to your LAN
- Firewall blocking UDP — allow UDP ports 50001–50003
- Different subnet — the client and radio must be on the same subnet (or have routing configured)
- Network Control disabled — enable "Remote Control" in your radio's network settings
Debug:
# Can you reach the radio?
ping 192.168.1.100
# Is the port open?
nc -u -z 192.168.1.100 50001
# Try discovery
icom-lan discover
"Authentication failed"¶
Symptom: AuthenticationError: Authentication failed (error=0xFEFFFFFF)
Causes:
- Wrong username/password — check your radio's Network User settings
- Too many connections — the radio supports limited concurrent connections. Disconnect other clients (RS-BA1, wfview, etc.)
- Account disabled — ensure the network user account is enabled
"CI-V response timed out"¶
Symptom: TimeoutError: CI-V response timed out
Causes:
- CI-V port negotiation failed — this usually means the conninfo exchange didn't complete properly
- Radio busy — another application may be holding the CI-V stream
- Network congestion — try increasing the timeout
- Command pacing too aggressive for current link/rig state — increase
ICOM_CIV_MIN_INTERVAL_MS(e.g., 50-80) for LAN, orICOM_SERIAL_CIV_MIN_INTERVAL_MSfor serial backend
Debug:
import logging
from icom_lan import create_radio, LanBackendConfig
logging.basicConfig(level=logging.DEBUG)
# This will show the full handshake sequence
config = LanBackendConfig(host="192.168.1.100", username="u", password="p")
async with create_radio(config) as radio:
freq = await radio.get_freq()
Look for:
- Status: civ_port=50002 — confirms port negotiation succeeded
- CI-V port not in status, using default — port negotiation failed, likely a GUID issue
"Scope over serial requires baudrate >= 115200"¶
Symptom: CommandError on enable_scope() / capture_scope_frame() with a low
serial baudrate.
Cause: Scope/waterfall CI-V traffic over serial is high-rate; low baud can starve regular command responses. The serial backend enforces a deterministic guardrail.
Fixes:
- Set the serial CI-V speed to at least
115200(recommended). - If you must run lower for diagnostics, use explicit override:
- Python API:
SerialBackendConfig(..., allow_low_baud_scope=True)when usingcreate_radio(config) - Env var:
ICOM_SERIAL_SCOPE_ALLOW_LOW_BAUD=1
When override is used, the backend logs a warning because timeout risk increases.
Connection drops after ~30 seconds¶
Symptom: Commands work initially, then start timing out.
Cause: Keep-alive pings stopped. This shouldn't happen under normal use, but can occur if:
- The event loop is blocked for extended periods
- The Python process is suspended
The library sends pings every 500ms automatically. If the radio doesn't receive pings for its timeout period (usually 10–30 seconds), it drops the connection.
Web UI API returns 401 Unauthorized¶
Symptom: GET /api/v1/info (or WebSocket connect) fails with HTTP 401.
Cause: Web server was started with --auth-token, but request does not include token.
Fixes:
For WebSocket clients, send either:
Authorization: Bearer <TOKEN>header, or?token=<TOKEN>query parameter.
radio_connect returns backend_recovering¶
Symptom: WebSocket response:
Cause: Backend is already in reconnect/recovery state. Parallel manual reconnect requests are rejected intentionally.
Fix: Wait for radio_ready=true in state updates before retrying manual connect.
Do not spam reconnect requests from frontend automation loops.
Mobile headset/lock-screen controls do nothing¶
Symptom: Volume/media buttons do not tune frequency and play/pause does not toggle PTT.
Cause: Browser does not expose the MediaSession API (navigator.mediaSession), so handlers are not registered.
Fixes:
- Verify behavior in a browser/platform with MediaSession support.
- Use on-screen controls as fallback (expected behavior on unsupported browsers).
Web UI polling appears slower on low battery¶
Symptom: State updates arrive less frequently on mobile devices with low battery.
Cause: Frontend intentionally increases /api/v1/state polling interval when battery is low and not charging:
- 10–20% -> 2x interval
- <=10% -> 4x interval
Fixes / Notes:
- Charge device to restore normal polling cadence.
- This optimization is skipped automatically on browsers without Battery Status API support.
Mobile v2 gestures are not available¶
Symptom: Swipe-to-dismiss bottom sheets and touch-first mobile layout are missing.
Cause: UI version defaults to v1 unless v2 is selected.
Fixes:
- Open Web UI with
?ui=v2query parameter. - Keep v2 selected in localStorage for subsequent sessions.
Command Issues¶
"Radio rejected set_frequency"¶
Symptom: CommandError: Radio rejected set_frequency(999999999)
The radio returned NAK (0xFA). Possible causes:
- Frequency out of the radio's supported range
- Radio is in a mode that doesn't allow frequency changes
- VFO lock is enabled
SWR/ALC always returns 0¶
These meters only report values during transmit. When receiving, they return 0.
CW text not sending¶
- Ensure the radio is in CW mode (
await radio.set_mode("CW")) - Check that CW keying speed is set appropriately on the radio
- Text must be ASCII A–Z, 0–9
Network Tips¶
Static IP¶
Assign a static IP to your radio to avoid DHCP lease changes:
- IC-7610: Menu → Set → Network → IP Address — set to Manual
- Use an IP outside your DHCP range
WiFi vs Ethernet¶
- Ethernet is more reliable with lower latency
- WiFi (IC-705) works but may experience higher packet loss
- For WiFi radios, increase the timeout:
timeout=10.0
VPN / Remote Access¶
The library works over VPN tunnels if UDP traffic is forwarded:
- Ensure your VPN supports UDP
- Allow ports 50001–50003
- Increase timeout for high-latency links
- Discovery (broadcast) won't work over VPN — specify the radio's IP directly
Retry / Fail-Fast Policy¶
Recommended policy for real-radio automation:
- Retry allowed (soft-fail): idempotent reads (
get_*) and non-critical telemetry. - Retry with recovery: command timeout after all retries -> one reconnect recovery path -> retry command once.
- Fail-fast (no blind retries): safety-critical toggles (
PTT,power_control, CW stop/start transactions) when state uncertainty is dangerous. - Always log on timeout: command name, attempt, timeout flag, recovered flag, duration.
In integration soak, use structured JSON logs with canonical fields:
test,step,cmd,attempt,timeout,recovered,duration_ms
Soak / Integration Diagnostics¶
Use soak mode to capture rare timeout behavior with structured logs:
export ICOM_SOAK_SECONDS=120
pytest -m integration tests/integration/test_radio_integration.py::TestSoak::test_soak_retries_and_logging -q -s
Look for:
{"ev":"timeout", ...}— timeout event{"ev":"recover", ...}— reconnect recovery attemptsSOAK_SUMMARY {...}— final counters (timeouts,timeouts_unrecovered, etc.)
Getting Help¶
- Enable debug logging (see above)
- Open an issue with:
- Your radio model
- Python version
- OS
- Debug log output
- Steps to reproduce
CI-V Commands Timeout During Scope/Waterfall¶
Symptom: get_frequency(), get_power() etc. return cached values or raise
TimeoutError while scope/waterfall is active.
Cause: Fixed in v0.8.0. In earlier versions, the RX pump processed one packet at a time. Scope data (~225 packets/sec) would queue ahead of command responses.
Solution: Upgrade to v0.8.0+. The drain-all RX pattern processes all queued packets each iteration.
Reconnect After Disconnect Takes Too Long¶
Symptom: After clicking Disconnect then Connect, the radio doesn't respond for 30-60 seconds.
Cause: Fixed in v0.8.0. Earlier versions did a full disconnect (including the control transport) and then a full reconnect with discovery. IC-7610 doesn't respond to discovery for ~60s after a recent session.
Solution: v0.8.0 uses soft disconnect/reconnect — only the CI-V data stream is closed. The control transport stays alive, so reconnect skips discovery and authentication entirely. Reconnect takes ~1 second.
Connection Fails With civ_port=0¶
Symptom: Log shows Status: civ_port=0, audio_port=0 repeatedly.
Cause: The radio needs time to recover between connections. Rapid reconnects (especially during development/testing) cause this.
Solutions:
1. Wait 30–60 seconds before reconnecting
2. v0.8.0+ uses optimistic default ports — connects instantly even with civ_port=0
3. If persistent: power-cycle the radio's network (Menu → Set → Network → LAN → Off/On)
Audio Cuts Out on Mobile (Safari iOS)¶
Symptom: Audio stops when Safari goes to background, doesn't resume on return.
Cause: iOS suspends WebSocket connections and AudioContext in background tabs.
Solution: v0.8.0+ adds visibilitychange listener that resumes AudioContext
and reconnects the audio WebSocket when the tab returns to foreground. Audio
may stutter briefly during reconnection.
Audio Stutters Over VPN/Tailscale¶
Symptom: Audio playback has gaps or stutters when accessing the Web UI remotely.
Cause: Network jitter from VPN tunneling.
Solution: v0.8.0+ uses a 200ms jitter buffer (up from 50ms). For very high latency connections, this may still be insufficient — consider a local deployment.
TX Audio Has No Modulation on macOS (Web UI / Bridge)¶
Symptom: PTT toggles ON, but transmitted audio is silent or very weak.
Typical logs:
audio: TX transcoder unavailable (opus codec missing?)- Opus library import failures from
opuslib.
Cause: On macOS, opuslib may fail to locate Homebrew libopus automatically.
Fixes:
# Install libopus via Homebrew
brew install opus
# Apply project patch for opuslib path detection
python scripts/patch_opuslib_macos.py
Then restart the app and retest TX audio. See detailed notes:
docs/opuslib-macos-fix.md.
Serial Backend Issues (IC-7610 USB)¶
"No such file or directory: /dev/cu.usbserial-..."¶
Symptom: FileNotFoundError or SerialException when connecting.
Causes: 1. USB cable not connected 2. Radio not powered on 3. Wrong device path
Solutions:
# List available serial devices (macOS)
ls -l /dev/cu.usbserial-*
# Linux
ls -l /dev/ttyUSB*
# Wait 5-10 seconds after power-on for device to appear
"CI-V USB Port must be set to CI-V, not REMOTE"¶
Symptom: Serial connection opens, but CI-V commands fail with timeout or NAK.
Cause: Radio's CI-V USB Port setting is in [REMOTE] mode (RS-BA1), not Link to [CI-V].
Solution:
1. On IC-7610: Menu → Set → Connectors → CI-V → CI-V USB Port
2. Set to Link to [CI-V] (NOT [REMOTE])
3. Disconnect/reconnect USB cable
4. Retry connection
Critical Hardware Finding
This was confirmed with live IC-7610 hardware validation (issue #146, 2026-03-06). [REMOTE] mode blocks serial CI-V commands. Use Link to [CI-V] for icom-lan serial backend.
"Audio device 'IC-7610 USB Audio' not found"¶
Symptom: AudioError or sounddevice exception when starting audio.
Causes: 1. USB audio not enabled on radio 2. Wrong device name 3. sounddevice/numpy not installed
Solutions:
# List available audio devices
icom-lan --list-audio-devices
icom-lan --list-audio-devices --json
# Check radio settings:
# Menu → Set → Connectors → USB Audio → USB Audio (RX/TX) → Enabled
# Install serial + USB audio dependencies if missing
pip install 'icom-lan[serial,bridge]'
"Scope over serial requires baudrate >= 115200"¶
Symptom: CommandError when calling enable_scope() or capture_scope_frame() on serial backend with baud < 115200.
Cause: Scope CI-V traffic is high-rate (~225 packets/sec on LAN). Lower serial baud rates cannot sustain this without starving command responses. The serial backend enforces a deterministic guardrail.
Solutions: 1. Recommended: Set CI-V USB Baud Rate to 115200 or higher in radio settings: - Menu → Set → Connectors → CI-V → CI-V USB Baud Rate → 115200 2. Override (use with caution for debugging only):
Python API: The library will log a warning about increased timeout risk.Serial CI-V commands time out under load¶
Symptom: TimeoutError on CI-V commands when audio or scope is active.
Causes: 1. Baud rate too low for combined traffic 2. CI-V pacing too aggressive
Solutions:
# Increase serial CI-V pacing interval (default 50 ms)
export ICOM_SERIAL_CIV_MIN_INTERVAL_MS=80
icom-lan --backend serial status
# Or use higher baud rate (radio setting)
# Menu → Set → Connectors → CI-V → CI-V USB Baud Rate → 115200
USB audio RX works, but TX does not¶
Symptom: Can hear radio RX audio, but transmit from computer does not work.
Causes: 1. Radio USB Audio TX not enabled 2. PTT not activated 3. Wrong TX device selected
Solutions:
# Check radio setting:
# Menu → Set → Connectors → USB Audio → USB Audio TX → Enabled
# Verify TX device name matches RX
icom-lan --list-audio-devices
# Explicitly set TX device
icom-lan --backend serial --tx-device "IC-7610 USB Audio" audio tx --in test.wav
# Ensure PTT is active during TX (library handles this automatically for audio tx)
Permission denied on /dev/cu.usbserial-*¶
Symptom: PermissionError when opening serial device.
Cause: User lacks permissions (rare on macOS, more common on Linux).
Solutions:
# Linux: add user to dialout group
sudo usermod -a -G dialout $USER
# Logout/login required
# macOS: check ownership (typically world-readable by default)
ls -l /dev/cu.usbserial-*
# Should show: crw-rw-rw- root wheel
# Temporary workaround (not recommended for production)
sudo chmod 666 /dev/cu.usbserial-XXXXXX