ESP32 GPIO 34, 35, 36 and 39 do not output: input-only pins

On the classic ESP32, GPIO 34, 35, 36 and 39 can only read. They cannot drive an output, and they have no internal pull-up or pull-down.

What the message means

These pins are meant for analog and digital input. digitalWrite on them has no effect, and INPUT_PULLUP does nothing.

Fix it in this order

  1. Move outputs such as LEDs, relays and motor driver inputs to a normal GPIO, for example 16, 17, 18, 19, 21, 22, 23, 25, 26 or 27.
  2. For a button on these pins add an external pull-up or pull-down resistor of about 10 kohm.
  3. Use them for sensors and analog inputs, which is what they are good at.
  4. Check your exact module, since pin availability differs between ESP32 variants.

Why it happens

On the classic ESP32, GPIO 34, 35, 36 and 39 are input-only. They cannot drive an output and have no internal pull-up or pull-down resistors, so INPUT_PULLUP does nothing there. If a button needs a pull-up, add an external resistor, for example 10 kΩ to 3.3 V.

Use them for analog inputs and for sensors that already drive a clean signal, and put LEDs, relays and motor drivers on output-capable pins. These four are on ADC1, which can be read while Wi-Fi is active.

If you see this, do this

You seeDo this
Output never changesInput-only pin. Move it.
Button reads random valuesAdd an external resistor.

ESP32 pinout, wiring checker, GPIO 12 boot fail.

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

Each ESP32 pad has an output driver and an input buffer that can be switched on or off. On GPIO 34, 35, 36 and 39 the chip designers left out the output driver and the internal pull resistors. These pads are meant for analog and digital sensing only, so a call to digitalWrite does nothing, and INPUT_PULLUP behaves like a plain INPUT. Because there is no pull-up, a pin with nothing connected reads random values.

The four pins also have friendly names. GPIO 36 and 39 are labelled SENSOR_VP and SENSOR_VN on many boards, and the group belongs to ADC1. That is useful for a battery voltage divider or an analog sensor, where ADC1 can be read while Wi-Fi is on. It is the wrong choice for an LED, a relay or a motor driver input. Module pinouts differ between ESP32 variants, so match the table to your exact chip.

How to confirm the cause

  • Find the pinout sheet for your exact board and look for the words input only next to 34, 35, 36 and 39.
  • Set the suspect pin to OUTPUT, write HIGH, and measure with a multimeter against GND. A reading near 0 V while the pin is high confirms that it cannot drive.
  • Move the same LED to a normal pin such as 25 and run the same code. If it works, the pin was the cause, not the wiring.
  • For a button that gives random readings, print digitalRead over serial with the button untouched. Flickering between 0 and 1 means the input is floating and needs an external pull resistor.
  • Check whether the label on your board is a GPIO number or a physical pin position. Many dev boards print GPIO numbers, but some print different names.

Worked example

A button on an input-only pin with an external pull-up, and an LED on a normal pin:

const int BUTTON_PIN = 34;  // input only; 10 kohm from this pin to 3.3 V
const int LED_PIN    = 25;  // ordinary output-capable GPIO

void setup() {
  pinMode(BUTTON_PIN, INPUT);    // INPUT_PULLUP would do nothing here
  pinMode(LED_PIN, OUTPUT);
}

void loop() {
  // button wired between the pin and GND: pressed = LOW
  digitalWrite(LED_PIN, digitalRead(BUTTON_PIN) == LOW ? HIGH : LOW);
}

Common mistakes

  • Using INPUT_PULLUP on these pins and expecting a pull-up.
  • Connecting a 5 V sensor output straight to a pin. ESP32 pins tolerate 3.3 V only.
  • Choosing GPIO 6 to 11 instead because they look free. On many modules they connect to the flash chip.
  • Assuming a newer ESP32 variant has the same input-only pins as the original.

If this did not fix it

  • The pin may be used by something else: a boot strapping function, an on-board LED, or a library that claimed it.
  • The board’s printed labels may not be GPIO numbers. Check the wiring against the pinout, not the silkscreen alone.
  • A missing common ground between the ESP32 and the device it drives makes outputs look dead even on valid pins.