Python serial: Permission denied /dev/ttyUSB0 or /dev/ttyACM0 on Linux

On many Linux systems your user must be in the dialout group to open a serial port. Add yourself, then sign out and in.

What the message means

Serial devices belong to a group. Without membership the system refuses to open the port.

Fix it in this order

  1. Run sudo usermod -a -G dialout $USER, then log out and log in again.
  2. Check the port name with ls /dev/tty* before and after plugging the board in.
  3. Close the Arduino serial monitor or other programs that hold the port.
  4. Check the user is in the group with the groups command.
  5. Use sudo only for a quick test, not as the lasting fix.

Why it happens

On many Linux systems the serial device files belong to a group, often called dialout, and only its members may open them. If your user is not in the group, the system refuses to open the port and you see permission denied.

Group changes apply at the next login, which is why the page asks you to sign out and in. If the port is busy rather than forbidden, close any program that holds it, such as a serial monitor. Group names can differ between distributions.

If you see this, do this

You seeDo this
Permission deniedGroup membership.
Device busyAnother program holds the port.

serial monitor shows nothing, board not detected.

Last reviewed: November 2026. These are the usual causes and the order that finds them fastest. Test on your own board; clones and cables differ.

Why this happens

On Linux, a serial adapter appears as a device file such as /dev/ttyUSB0 or /dev/ttyACM0. The file is owned by root and a group, with permissions that let the owner and the group read and write but not others. On Debian and Ubuntu the group is usually dialout. On some other systems, for example Arch, it is uucp.

Your account must be a member of that group. Group membership is read when you log in, so a change made in a running session has no effect until you sign out and in again.

How to confirm the cause

  • Run ls -l /dev/ttyUSB0 and read the group name in the output.
  • Run groups. The group from the previous step must be in the list.
  • Run dmesg | tail just after plugging the board in to see the device name it was given.
  • If the group is right and the error remains, run lsof /dev/ttyUSB0 or fuser /dev/ttyUSB0 to see which program holds the port.
  • Check that no other service is claiming the adapter.

Worked example

The full sequence for a Debian-style system.

ls -l /dev/ttyUSB0
groups
sudo usermod -a -G dialout $USER
# log out and log in again
groups
python3 -c "import serial; s = serial.Serial('/dev/ttyUSB0', 115200, timeout=1); print(s.name)"

Common mistakes

  • Using usermod -G without the -a flag. That replaces all your other groups.
  • Not logging out after the change.
  • Using chmod 777 on the device. It resets when the adapter is unplugged.
  • Using sudo with a Python virtual environment, which then runs a different Python.
  • Mixing up ttyUSB0 and ttyACM0. The number or type can change between plugs.

If this did not fix it

  • The port is busy because another program, such as a serial monitor, has it open.
  • No device file at all, which points to a charge-only cable or a missing driver.
  • A service that grabs serial adapters on some desktop systems. Check the system log when the device appears.