Troubleshooting
Serial communication fails in predictable ways. This guide covers the most common errors, how to diagnose them, and the recovery patterns that work.
All troubleshooting operations described here are performed through your MCP client. Ask the assistant to check port status, re-enumerate devices, or test connections — it calls the appropriate mcserial tools on your behalf.
Connection Errors
Section titled “Connection Errors””Port is already open”
Section titled “”Port is already open””You attempted to open a port that mcserial has already opened. This happens when:
- A previous session opened the port but the close was never called
- You called
open_serial_porttwice on the same device - Multiple agents or conversations are trying to use the same hardware
Recovery:
// Close the existing connection first// close_serial_port(port="/dev/ttyUSB0"){ "success": true, "port": "/dev/ttyUSB0"}
// Now open fresh// open_serial_port(port="/dev/ttyUSB0", baudrate=115200)If you are not sure which ports are open, check the connection status:
// get_connection_status(){ "open_connections": [ { "port": "/dev/ttyUSB0", "mode": "rs232", "baudrate": 115200 } ]}“Port is not open”
Section titled ““Port is not open””You tried to read, write, or configure a port that is not currently open in mcserial.
Common causes:
- The port was never opened
- The port was closed by a previous operation
- The device was physically disconnected, causing an automatic close
Recovery:
Open the port before performing operations:
// open_serial_port(port="/dev/ttyUSB0", baudrate=115200)If the device was disconnected, re-enumerate to confirm it is back:
// list_serial_ports(){ "ports": [ { "device": "/dev/ttyUSB0", "description": "USB-Serial Controller", "hwid": "USB VID:PID=0403:6001" } ]}“Maximum connections reached”
Section titled ““Maximum connections reached””mcserial limits concurrent open ports to prevent resource exhaustion (default: 10). You have hit that limit.
Recovery:
Close ports you are no longer using:
// get_connection_status()// Identify unused ports, then:// close_serial_port(port="/dev/ttyUSB1")If you genuinely need more concurrent connections, increase the limit via environment variable before starting mcserial:
export MCSERIAL_MAX_CONNECTIONS=20See the Environment Variables reference for details.
Permission Errors
Section titled “Permission Errors””Permission denied” (Linux)
Section titled “”Permission denied” (Linux)”The user running mcserial does not have access to the serial device. On Linux, serial ports are typically owned by the dialout or uucp group.
# Add your user to the dialout groupsudo usermod -a -G dialout $USER
# Log out and back in for the change to take effect# Or use newgrp for the current session:newgrp dialout# Check your groupsgroups# Should include: dialout
# Check device permissionsls -la /dev/ttyUSB0# Should show: crw-rw---- 1 root dialout ...udev Rules for Persistent Permissions
Section titled “udev Rules for Persistent Permissions”If devices keep losing permissions after reconnection, create a udev rule:
SUBSYSTEM=="tty", GROUP="dialout", MODE="0660"
# Reload rulessudo udevadm control --reload-rulessudo udevadm triggerFor specific devices (e.g., all FTDI adapters):
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", GROUP="dialout", MODE="0660"Device Disconnection
Section titled “Device Disconnection”Detecting a disconnected device
Section titled “Detecting a disconnected device”When a USB serial device is physically unplugged, subsequent operations return errors. The exact error varies by operation:
- Reads may return empty data or timeout
- Writes may throw
serial.serialutil.SerialException - Status queries may report the port as closed
Detection pattern:
// Try a simple read with short timeout// read_serial(port="/dev/ttyUSB0", size=1, timeout=0.5)
// If the device is gone, you'll see:{ "error": "Port /dev/ttyUSB0 is not open", "success": false}Re-enumeration after reconnection
Section titled “Re-enumeration after reconnection”After plugging a device back in, it may appear on a different port (e.g., /dev/ttyUSB1 instead of /dev/ttyUSB0). Always re-enumerate:
// list_serial_ports(grep="FTDI"){ "ports": [ { "device": "/dev/ttyUSB1", "description": "FT232R USB UART", "hwid": "USB VID:PID=0403:6001 SER=A50285BI" } ]}Graceful reconnection workflow
Section titled “Graceful reconnection workflow”-
Detect the disconnection
Monitor for errors or empty reads that indicate the device is gone.
-
Close the stale connection
// close_serial_port(port="/dev/ttyUSB0")This cleans up mcserial’s internal state even if the device is gone.
-
Wait for reconnection
Poll
list_serial_portsuntil the device reappears. -
Open the new port
// list_serial_ports(grep="FTDI")// open_serial_port(port="/dev/ttyUSB1", baudrate=115200)
No Response / Timeout Issues
Section titled “No Response / Timeout Issues”Differentiating “no data” from “wrong baud rate”
Section titled “Differentiating “no data” from “wrong baud rate””When read_serial returns empty, the cause could be:
- Correct baud, device not sending — the device is connected but silent
- Wrong baud rate — data is arriving but garbled or misframed
- Hardware issue — cable problem, device powered off, TX/RX swapped
Diagnosis steps:
// 1. Check if the port is actually open and configured// get_connection_status()
// 2. Try auto-baud detection on an open port// detect_baud_rate(port="/dev/ttyUSB0", probe="U", timeout_per_rate=0.5){ "detected_baudrate": 115200, "confidence": 0.85, "results": [ {"baudrate": 115200, "score": 0.85}, {"baudrate": 9600, "score": 0.12} ]}If auto-detection succeeds with a different baud rate, reconfigure:
// configure_serial(port="/dev/ttyUSB0", baudrate=115200)Slow devices and timeout adjustment
Section titled “Slow devices and timeout adjustment”Some devices take time to respond:
- GPS receivers during cold start: 30-60 seconds
- Industrial sensors with long sample cycles
- Devices that process commands before responding
Adjust the read timeout:
// configure_serial(port="/dev/ttyUSB0", timeout=10.0)Or specify per-read:
// read_serial(port="/dev/ttyUSB0", timeout=30.0)See the Timeout Tuning guide for detailed guidance.
RS-485 Bus Issues
Section titled “RS-485 Bus Issues”No response from any device
Section titled “No response from any device”If RS-485 transactions return nothing, check:
- Termination — RS-485 buses need 120Ω termination resistors at each end
- Bias resistors — long buses or noisy environments may need bias
- A/B polarity — some adapters swap A and B (try swapping the wires)
- DE/RE timing — the driver enable timing may be wrong
Check RS-485 configuration:
// The port should be in RS-485 mode// get_connection_status(){ "open_connections": [ { "port": "/dev/ttyUSB0", "mode": "rs485", "rs485_config": { "enabled": true, "rts_level_for_tx": true, "delay_before_tx": 0, "delay_before_rx": 0.005 } } ]}Bus contention (garbled responses)
Section titled “Bus contention (garbled responses)”If multiple devices respond simultaneously or responses are corrupted:
- Address collision — two devices have the same address
- Timing overlap — insufficient turnaround delay between TX and RX
- Echo enabled — loopback mode is creating interference
Increase turnaround delay:
// set_rs485_mode(port="/dev/ttyUSB0", delay_before_rx=0.01)Scanning for responsive devices
Section titled “Scanning for responsive devices”Use rs485_scan_addresses to discover which devices respond:
// rs485_scan_addresses(// port="/dev/ttyUSB0",// start_address=1,// end_address=32,// response_timeout=0.1// ){ "success": true, "responding_addresses": [1, 5, 12], "total_scanned": 32, "scan_time_seconds": 3.2}Auto-Baud Detection Failures
Section titled “Auto-Baud Detection Failures””No data received or low confidence”
Section titled “”No data received or low confidence””Auto-baud detection relies on seeing data to analyze. It fails when:
- The device is not sending anything (waiting for a command)
- The device requires a specific wake-up sequence
- All baud rates produced only garbled data (hardware issue)
Try with a probe string:
// Some devices echo input or respond to specific commands// open_serial_port(// port="/dev/ttyUSB0",// autobaud_probe="ATI\r\n",// autobaud_timeout=0.5// )The probe is sent at each candidate baud rate. If the device echoes or responds, the detection has data to analyze.
Common probe strings:
| Device Type | Probe | Notes |
|---|---|---|
| Modem/AT command | ATI\r\n | Returns device info |
| Echo-enabled | UUUUU | 0x55 is a sync pattern |
| GPS (NMEA) | (none) | Usually sends continuously |
| Modbus RTU | (protocol-specific) | Send a read holding register command |
Detection returns wrong baud rate
Section titled “Detection returns wrong baud rate”If detection consistently picks the wrong rate, the heuristics may be confused by the data pattern. Fall back to explicit baud rate specification:
// open_serial_port(port="/dev/ttyUSB0", baudrate=115200)File Transfer Failures
Section titled “File Transfer Failures””Receiver not ready” or immediate timeout
Section titled “”Receiver not ready” or immediate timeout”The remote device must be in receive mode before you call file_transfer_send. For XMODEM and YMODEM, start the receiver first.
Typical workflow:
// 1. Send the receive command to the device// write_serial(port="/dev/ttyUSB0", data="rx firmware.bin\r\n")
// 2. Wait for the receiver to start (look for NAK or 'C' for CRC mode)// read_serial(port="/dev/ttyUSB0", timeout=5.0)
// 3. Now send the file// file_transfer_send(port="/dev/ttyUSB0", file_path="/tmp/firmware.bin", protocol="xmodem")Interrupted ZMODEM transfer
Section titled “Interrupted ZMODEM transfer”ZMODEM supports resume. If a transfer was interrupted:
// Just try sending again — ZMODEM negotiates resume automatically// file_transfer_send(port="/dev/ttyUSB0", file_path="/tmp/large_file.bin", protocol="zmodem")The receiver should offer to resume from where it left off, skipping already-received data.
Block errors and retransmissions
Section titled “Block errors and retransmissions”All protocols have error detection and will request retransmission of corrupted blocks. However, excessive errors indicate:
- Electrical noise — use shielded cables, add ferrite chokes
- Baud rate too high — reduce baud rate for long cables
- Flow control issues — enable RTS/CTS for high-speed transfers
See File Transfers for protocol-specific details.
Quick Reference: Error → Action
Section titled “Quick Reference: Error → Action”| Error Message | Likely Cause | First Action |
|---|---|---|
| ”Port is already open” | Double open | close_serial_port, then reopen |
| ”Port is not open” | Never opened or disconnected | open_serial_port |
| ”Permission denied” | Missing dialout group | sudo usermod -a -G dialout $USER |
| ”Maximum connections reached” | Too many open ports | Close unused ports |
| ”Device or resource busy” | Another process has the port | Check lsof /dev/ttyUSB0 |
| Empty reads, no data | Wrong baud or device silent | detect_baud_rate or probe |
| Garbled text | Wrong baud rate | configure_serial(baudrate=...) |
| ”Unsupported URL scheme” | Typo in URL | Check scheme spelling |
| ”cp2110:// requires hidapi” | Missing extra | pip install mcserial[cp2110] |