How to fix Linux ESP32 PlatformIO PermissionError: [Errno 13] Permission denied: '/dev/ttyUSB0'

Problem:

When trying to flash a ESP8266 or ESP32 board on Linux, you see an error message like

Warning! Please install `99-platformio-udev.rules`. 
More details: https://docs.platformio.org/page/faq.html#platformio-udev-rules

Auto-detected: /dev/ttyUSB0
Uploading .pio/build/esp32dev/firmware.bin
esptool.py v3.1
Serial port /dev/ttyUSB0
Traceback (most recent call last):
  File "/home/uli/.platformio/penv/lib/python3.8/site-packages/serial/serialposix.py", line 322, in open
    self.fd = os.open(self.portstr, os.O_RDWR | os.O_NOCTTY | os.O_NONBLOCK)
PermissionError: [Errno 13] Permission denied: '/dev/ttyUSB0'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/uli/.platformio/packages/tool-esptoolpy/esptool.py", line 4582, in <module>
    _main()
  File "/home/uli/.platformio/packages/tool-esptoolpy/esptool.py", line 4575, in _main
    main()
  File "/home/uli/.platformio/packages/tool-esptoolpy/esptool.py", line 4074, in main
    esp = esp or get_default_connected_device(ser_list, port=args.port, connect_attempts=args.connect_attempts,
  File "/home/uli/.platformio/packages/tool-esptoolpy/esptool.py", line 120, in get_default_connected_device
    _esp = chip_class(each_port, initial_baud, trace)
  File "/home/uli/.platformio/packages/tool-esptoolpy/esptool.py", line 313, in __init__
    self._port = serial.serial_for_url(port)
  File "/home/uli/.platformio/penv/lib/python3.8/site-packages/serial/__init__.py", line 90, in serial_for_url
    instance.open()
  File "/home/uli/.platformio/penv/lib/python3.8/site-packages/serial/serialposix.py", line 325, in open
    raise SerialException(msg.errno, "could not open port {}: {}".format(self._port, msg))
serial.serialutil.SerialException: [Errno 13] could not open port /dev/ttyUSB0: [Errno 13] Permission denied: '/dev/ttyUSB0'

Solution

As described at the top of the error message, install the PlatformIO udev rules:

curl -fsSL https://raw.githubusercontent.com/platformio/platformio-core/master/scripts/99-platformio-udev.rules | sudo tee /etc/udev/rules.d/99-platformio-udev.rules

then restart udev:

sudo systemctl restart udev

After that, unplug an re-plug your ESP32 board in order for the changes to take effect

Additionally, I recommend adding your user to the dialout group - the Linux group that owns most USB devices:

sudo usermod -a -G dialout $USER

In order for the changes to take effect, log out from your current session completely and log back in again (or reboot). While not strictly neccessary in order to fix this specific error message, it helps in preventing future USB permission issues.