Skip to content
Guide
15 min read
October 17, 2026

MicroPython Troubleshooting: Thonny Can't Connect, ImportError, OSError and MemoryError

A symptom-first troubleshooting guide for MicroPython on ESP32 and Pico: what each error means, how to confirm the cause and the shortest fix, from USB cables and full file systems to MemoryError, heap fragmentation and gc.collect.

MicroPython Troubleshooting: Thonny Can't Connect, ImportError, OSError and MemoryError

MicroPython makes microcontroller development approachable, but errors can arise from USB cables, serial ports, firmware, Python modules, GPIO wiring, network connections, or limited memory. The fastest way to solve a problem is to identify which layer is failing and test that layer with the smallest possible example. Reflashing firmware or rewriting a complete project before collecting evidence can erase useful files and make the original cause harder to find.

This troubleshooting guide covers common Thonny connection problems, REPL and startup-script failures, ImportError, GPIO and sensor errors, Wi-Fi and MQTT issues, and memory limitations. The exact fix depends on your board, MicroPython port, firmware version, and installed drivers. Record those details before changing anything, and keep backups of scripts and configuration files.

1. Start with a reproducible diagnosis

Before changing settings, write down the exact board model, chip variant, operating system, editor version, MicroPython firmware build, and complete error message. Note what action triggered the error and whether the same script worked earlier. If a sensor or display is involved, record its exact model and wiring. A photo of a low-voltage circuit can help, but do not include passwords, API keys, Wi-Fi credentials, or other secrets.

Reduce the problem to the smallest test that still fails. If a full application uses Wi-Fi, a display, a sensor, and PWM, test the REPL first, then one peripheral at a time. Change only one variable between attempts and keep a short log of results. This makes it possible to distinguish a code problem from a cable, firmware, driver, or power problem.

Back up files stored on the board before flashing firmware or erasing its filesystem. Some recovery procedures remove main.py, installed drivers, and configuration files. If the board is running a broken startup script, try interrupting it from the REPL or follow the board-specific recovery instructions before wiping anything.

2. Thonny cannot find or open the serial port

No port appears in the interpreter menu: first use a known data-capable USB cable; charge-only cables can power a board without providing data. Try another USB port and avoid an unpowered hub. Check whether the operating system detects a serial device and install the board's appropriate USB-to-serial driver if needed. Some boards use native USB, while others use a separate bridge chip, so the correct driver depends on the hardware.

The port appears but cannot be opened: close other programs that may be using it, including a second editor window, serial terminal, or monitor. Disconnect and reconnect the board, then select the port again. On Windows, Device Manager can show whether the device appears and whether a driver warning is present. Do not guess a COM number based on an old screenshot; select the device currently associated with the board.

Thonny connects but shows no prompt: confirm that the interpreter is set to MicroPython for the relevant board rather than desktop Python. Press the board's reset button if appropriate, then try a soft reboot or interrupt a running program. If a script prints continuously, the prompt may be hidden among output. If connection still fails, test another cable and computer before assuming firmware is corrupt.

3. The REPL freezes or a startup script keeps restarting

A long-running loop can make the prompt appear unresponsive even though the interpreter is working. Try Ctrl+C in the REPL to interrupt it. If the program uses blocking I/O or has disabled normal interaction, reset the board and reconnect. A soft reboot restarts the interpreter, but a script saved as main.py may run again immediately.

If main.py repeatedly crashes at startup, keep a backup on your computer. Attempt to interrupt execution early after reset or use the documented safe-mode/recovery process for your board. Recovery methods differ by port and firmware; do not assume a button sequence for one board works on another. If necessary, connect using the correct bootloader procedure and replace the faulty startup file only after confirming the correct filesystem and backup.

During development, keep a minimal startup file and run larger experiments manually until they are stable. Avoid infinite loops with no delay or yield when the application needs to handle network requests, serial input, or other tasks. Add bounded waits, error messages, and a known way to stop the program. Do not repeatedly reflash firmware as the first response to an ordinary Python exception.

4. Understand ImportError and missing modules

An ImportError or ModuleNotFoundError means the interpreter could not load the requested module. The module may not be built into the firmware, the driver file may be missing from the board, the name may be misspelled, or the module may depend on another file that is absent. A library installed in desktop Python is not automatically available on a microcontroller.

Check the import name and file location. In Thonny, confirm whether the file is on the computer or the MicroPython device. If the project uses import ssd1306, the corresponding driver file must be accessible under the expected module name. If it uses from umqtt.simple import MQTTClient, verify that the installed folder structure matches that import path and that the client library supports the firmware version.

Install drivers only from sources you trust, and keep a copy of the exact version. Some libraries rely on native modules that cannot simply be copied as Python files. If a package depends on unavailable native features, choose a compatible implementation rather than repeatedly copying the same file. Test one import at a time before integrating the library into a large program.

5. Fix OSError from files, sensors, and peripherals

OSError is a broad exception used for many operating-system and hardware I/O failures. Its meaning depends on the operation and port. It can indicate a failed sensor transaction, a disconnected network, a filesystem problem, or a peripheral that did not respond. Read the full traceback and identify the line that failed instead of treating every OSError as the same fault.

For I²C sensors and displays, check supply, ground, SDA/SCL wiring, address, pull-ups, and supported bus speed. Run i2c.scan() as a separate test. If a device is not detected, a higher-level driver cannot make it appear. For a sensor that is detected but fails on a read, confirm the exact model, timing requirements, and driver API. Catch expected transient errors and report them, but avoid an empty except block that hides repeated failures.

For filesystem errors, verify that the target filesystem is mounted and that the filename and path are correct. For network errors, test Wi-Fi and broker reachability separately. Record the operation and error code where available; this is more informative than printing only “something failed.” If a device is electrically overheating or there is evidence of a short, disconnect power before further debugging.

6. Wi-Fi connection and timeout errors

A Wi-Fi failure may be caused by incorrect credentials, weak signal, router configuration, unsupported band, or a board/firmware mismatch. Confirm that the exact board includes Wi-Fi; not every microcontroller board does. For initial testing, keep the device near the access point and use a network configuration supported by the board. Do not publish real SSIDs and passwords in code examples, screenshots, or repositories.

Use a bounded connection wait so a missing network does not leave the program stuck forever:

import network, time
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect("YOUR_WIFI_NAME", "YOUR_WIFI_PASSWORD")
deadline = time.ticks_add(time.ticks_ms(), 15000)
while not wlan.isconnected() and time.ticks_diff(deadline, time.ticks_ms()) > 0:
    time.sleep_ms(250)
print("Connected:", wlan.isconnected())

Replace placeholders privately. If the connection fails, inspect the credentials, access-point band and security settings, signal strength, and router client isolation. Once connected, test the next service independently: DNS resolution, TCP reachability, or MQTT broker access may fail even when Wi-Fi is working. Add reconnect logic with a delay rather than retrying continuously in a tight loop.

7. Diagnose MemoryError and slow programs

Microcontrollers have limited RAM, and some MicroPython ports also have a small filesystem. MemoryError can occur when allocating large lists, strings, byte buffers, images, or network payloads. A 128×64 monochrome framebuffer alone needs roughly 1 KB of pixel data, but the driver and Python objects use additional memory. Larger displays, camera frames, JSON payloads, and multiple libraries can consume much more.

Reduce unnecessary allocations and avoid rebuilding large objects inside fast loops. Process data in small chunks, reuse buffers where supported, and avoid collecting unlimited log messages or sensor samples in a list. If your port supports garbage collection, import gc; gc.collect() can reclaim unreachable objects, but it cannot free memory still referenced by your program or fix a design that continually allocates more.

Measure before changing architecture. Print available heap information if the port exposes it, test features one by one, and remove unused modules. If a task needs large image buffers or complex networking, consider a board with more RAM or a more efficient library. Do not assume that a successful import means enough memory remains for the library's full runtime workload.

8. GPIO errors and unexpected hardware behaviour

A GPIO error can indicate an invalid pin number, a pin reserved for another function, an unsupported mode, or a board-specific restriction. Verify the exact pinout and the MicroPython documentation for your chip family. Board labels are not always physical header positions, and some pins affect boot behaviour or connect to flash, USB, or onboard peripherals. Start with a known-safe output and a current-limited LED circuit.

If a button reads the opposite of what you expect, check whether the input uses a pull-up or pull-down and whether the button connects to ground or supply. A pull-up configuration commonly reads 1 when open and 0 when pressed to ground. Mechanical contacts bounce, so a single press may produce several transitions unless you debounce it.

If a motor, relay, or servo causes resets, disconnect it and test the microcontroller alone. GPIO pins are for logic signals, not for directly powering inductive or high-current loads. Use a suitable driver and supply, common ground where appropriate, and protection components recommended by the load driver design. Never probe or rewire a powered circuit when there is a risk of shorting supply rails.

9. MQTT, sockets, and broker connection problems

If an MQTT client imports correctly but cannot connect, separate client-library problems from network and broker problems. Confirm that the broker service is running, the hostname or LAN IP is correct, the port matches its listener configuration, and firewall rules allow the connection. A desktop MQTT explorer is a client, not a broker service. If using a local broker, localhost from the ESP32 means the ESP32 itself, not the computer running the broker.

An authentication failure points toward credentials or broker access-control rules. A timeout may indicate routing, firewall, DNS, or service availability. A repeated disconnect may result from a duplicate client ID, weak Wi-Fi, keep-alive mismatch, or broker policy. Check broker logs when available and test with a desktop client on the same network. Confirm exact topic spelling and case when a subscriber sees no messages.

Do not expose an unauthenticated broker or raw microcontroller web server to the public internet. Use strong unique credentials and topic permissions, and TLS where supported and configured correctly. Treat connection strings, passwords, and certificates as secrets. A successful Wi-Fi connection alone does not prove that a remote service is reachable or secure.

10. A repeatable recovery checklist

When an error persists, return to a known baseline: back up the project; confirm the correct interpreter and port; test a simple REPL command; run a minimal program; verify each peripheral independently; and add networking or extra libraries only after the previous layer works. Preserve the exact traceback and change one variable at a time. After a successful fix, write down what caused the issue and how you confirmed the resolution.

Use official MicroPython documentation for the installed port and firmware, the exact board schematic or pinout, and the peripheral datasheet as primary references. Forum posts and copied snippets can be useful clues, but APIs change and similar-looking boards may have different pins or electrical limits. If an example uses a method missing from your firmware, find the documented equivalent rather than blindly changing unrelated settings.

SolderHub principle: diagnose from the simplest layer upward. Protect hardware first, preserve working files, and treat error messages as evidence. This approach is faster and safer than repeatedly reflashing the board or changing several parts of the project at once.

Signal In

Built from what makers search for

The lookups piling up in SolderHub's search bar every day shape what we publish next — new component pages, board guides, and firmware notes, sent out as they go live.

By subscribing you agree to our Privacy Policy. Unsubscribe anytime.