← index #17339Issue #17661
Related · high · value 4.506
QUERY · ISSUE

sta_if.status() unreliable

openby robtinkersopened 2025-05-22updated 2026-03-16
bugport-esp32

Port, board and/or hardware

esp32 port

MicroPython version

MicroPython v1.25.0 on 2025-04-15; Generic ESP32 module with ESP32

Reproduction

import network, time
from sys import print_exception

REAL_SSID = 'MyNetwork'
REAL_PASS = 'MyPassword'

NETWORKS = (('FakeNetwork1', '12345678'), (REAL_SSID, REAL_PASS), ('FakeNetwork2', '12345678'), ('FakeNetwork3', '12345678'))

STATUS_LOOKUP = {
    network.STAT_ASSOC_FAIL: 'ASSOC_FAIL',
    network.STAT_BEACON_TIMEOUT: 'BEACON_TIMEOUT',
    network.STAT_CONNECTING: 'CONNECTING',
    network.STAT_CONNECT_FAIL: 'CONNECT_FAIL',
    network.STAT_GOT_IP: 'GOT_IP',
    network.STAT_HANDSHAKE_TIMEOUT: 'HANDSHAKE_TIMEOUT',
    network.STAT_IDLE: 'IDLE',
    network.STAT_NO_AP_FOUND: 'NO_AP_FOUND',
    network.STAT_NO_AP_FOUND_IN_AUTHMODE_THRESHOLD: 'NO_AP_FOUND_IN_AUTHMODE_THRESHOLD',
    network.STAT_NO_AP_FOUND_IN_RSSI_THRESHOLD: 'NO_AP_FOUND_IN_RSSI_THRESHOLD',
    network.STAT_NO_AP_FOUND_W_COMPATIBLE_SECURITY: 'NO_AP_FOUND_W_COMPATIBLE_SECURITY',
    network.STAT_WRONG_PASSWORD: 'WRONG_PASSWORD',
}

def print_status_loop(interface, duration):
    old_status = None
    t0 = time.ticks_ms()
    while True:
        tt = time.ticks_diff(time.ticks_ms(), t0)
        if tt > duration * 1000:
            break
        status = interface.status()
        if old_status != status:
            old_status = status
            print(tt, STATUS_LOOKUP.get(status, str(status)))

sta_if = network.WLAN(network.STA_IF)
sta_if.active(True)

for network in NETWORKS:
    print( '======== disconnect()')
    try: sta_if.disconnect()
    except Exception as e: print_exception(e)
    print_status_loop(sta_if, 5)
    print(f'======== connect({network[0]}, ...)')
    sta_if.connect(*network)
    print_status_loop(sta_if, 5)

Expected behaviour

I would expect the connect() call to reliably initialise the status to something (CONNECTING?)

I would expect the disconnect() call to reliably set the status to something (IDLE?)

Observed behaviour

connect() only works as I expect if the previous connect() call eventually GOT_IP, but not otherwise.

disconnect() almost works as I expect if the previous connect() call eventually GOT_IP, but not otherwise.

======== disconnect()
0 IDLE
======== connect(FakeNetwork1, ...)
0 CONNECTING
2417 NO_AP_FOUND
======== disconnect()
0 NO_AP_FOUND
======== connect(MyNetwork, ...)
0 NO_AP_FOUND
1398 GOT_IP
======== disconnect()
0 GOT_IP
1 IDLE
======== connect(FakeNetwork2, ...)
0 IDLE
2417 NO_AP_FOUND
======== disconnect()
0 NO_AP_FOUND
======== connect(FakeNetwork3, ...)
0 NO_AP_FOUND

Additional Information

I would like to loop through a bunch of pre-configured wifi networks to find one that works (e.g. for a portable device).

Unfortunately if a .connect() call doesn't eventually connect (the usual case in my scenario), then polling .status() becomes unreliable and I have to guess an appropriate timer and wait for .isconnected() for each ssid/pass, significantly slowing down startup if the working network is down the list.

Code of Conduct

Yes, I agree

CANDIDATE · ISSUE

Repeatable OSError: Wifi Internal Error in sta_if.connect

openby robtinkersopened 2025-07-11updated 2026-03-15
bugport-esp32

Port, board and/or hardware

ESP32-C3 and S3

MicroPython version

MicroPython v1.25.0 on 2025-04-15; ESP32C3 module with ESP32C3

Reproduction

Power-cycle the board and run the following code (in my case, in Thonny):

import network, time
sta_if = network.WLAN(network.WLAN.IF_STA)
sta_if.active(True)

print('foo')
sta_if.connect("no-such-network", "password")
time.sleep(5)

print('bar')
sta_if.connect("no-such-network", "password")
time.sleep(5)

print('baz')

Expected behaviour

No response

Observed behaviour

foo
bar
Traceback (most recent call last):
  File "<stdin>", line 10, in <module>
OSError: Wifi Internal Error

(where line 10 is the second connect)

I get similar results when the first connect() is a real network with the wrong password, the second connect() is the same wrong network/password as the first, or the second connect() is a real network with the right password.

In fact, the sleep()s don't seem to be required either.

Additional Information

Power-cycling the board before running the test may be required for reproducibility.

Bug also manifests in the latest preview ESP32_GENERIC_C3-20250709-v1.26.0-preview.364.gdf05caea6.bin

and ESP32_GENERIC_S3-SPIRAM_OCT-20250709-v1.26.0-preview.364.gdf05caea6.bin

Unfortunately I don't have other boards to test with right now.

Code of Conduct

Yes, I agree

Keyboard

j / / n
next pair
k / / p
previous pair
1 / / h
show query pane
2 / / l
show candidate pane
c
copy suggested comment
r
toggle reasoning
g i
go to index
?
show this help
esc
close overlays

press ? or esc to close

copied