Another script, or an earlier run that did not clean up, is holding the pin. Stop it, and call GPIO.cleanup() at exit.
What the message means
The library remembers the pins you set up. If a script ended without cleaning up, or another program still runs, the pin shows as in use.
Fix it in this order
- Stop any other script that uses the same pin.
- Call GPIO.cleanup() in a finally block at the end of the program.
- Or turn the warning off with GPIO.setwarnings(False) once you know it is safe.
- Do not use one pin in two programs at the same time.
- Check the numbering mode, BCM or BOARD, and use it the same way everywhere.
Why it happens
The GPIO library keeps a record of which pins your program has set up. If a script ends without calling cleanup, or crashes, that record can be left behind, and the next run sees the pin as already in use. Another program that is still running can hold the same pin too.
Calling cleanup in a finally block runs it even when the program stops on an error. Turning the warning off hides the message but does not release a pin that another program is really using, so check for a running script first.
If you see this, do this
| You see | Do this |
|---|---|
| Appears on second run | Add cleanup. |
| Appears at once | Another program holds the pin. |
Related
Pi GPIO levels, I2C on the Pi.
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
RPi.GPIO keeps a table of the pins your program has configured. When you call setup on a pin, it checks whether the pin is already marked as in use, either by an earlier setup in the same program or because the pin was left in a non-default state by a program that stopped without cleaning up. The message is a warning, so the code continues anyway, but it is telling you that two things may be fighting over one pin.
GPIO.cleanup() resets the channels that your program configured back to inputs and clears the library’s record. If the program stops with an error or is killed, cleanup does not run. Putting it in a finally block makes it run on a normal exit, an exception and Ctrl+C. It will not release a pin held by a different running program, so the first step is to find out whether one is running.
How to confirm the cause
- List running Python programs with pgrep -af python. A leftover script from an earlier run is the most common holder.
- Check programs started automatically. Look at crontab -l and at systemd services that may run a script at boot.
- Read the pin state with pinctrl get 17 (or raspi-gpio get 17 on older images) after your program ends. A pin still shown as an output means it was not cleaned up.
- Confirm that every part of your code uses the same numbering mode, GPIO.BCM or GPIO.BOARD, since pin 17 means different pins in each.
- Check config.txt for overlays that claim pins, such as an extra serial port or a HAT driver.
Worked example
A script structure that cleans up on every exit path (17 is the BCM number of the example pin):
import RPi.GPIO as GPIO
import time
LED = 17
GPIO.setmode(GPIO.BCM)
GPIO.setup(LED, GPIO.OUT)
try:
while True:
GPIO.output(LED, GPIO.HIGH); time.sleep(0.5)
GPIO.output(LED, GPIO.LOW); time.sleep(0.5)
finally:
GPIO.cleanup()Common mistakes
- Calling GPIO.cleanup() at the start of the script instead of at the end.
- Calling cleanup in the middle of the program and then using the pins afterwards without setting them up again.
- Mixing BCM and BOARD numbering between two scripts.
- Stopping a script with kill -9, which skips every cleanup step.
- Hiding the warning with setwarnings(False) and never checking what holds the pin.
If this did not fix it
- Another GPIO library such as gpiozero or pigpio may be using the same pin in a different process.
- A device-tree overlay or a HAT can reserve pins at boot. Check the overlays in config.txt.
- A script launched from an IDE and another from the terminal can both be running at once.