September 13, 2026
ASSOC-REJECT status_code=1027: when the access point is full, Android blames your password
A new phone refused to join the rack's Wi-Fi and Android reported a wrong password. The supplicant log said ASSOC-REJECT — refused before the passphrase was ever checked. The access point's station table was full, and one of the slots was held by a device that wasn't ours.
We added a phone to the rack and it would not join the network. Android said the password was wrong. The password was not wrong. It took longer than it should have to work out why, so here is the whole thing, including the part where we were looking at the wrong layer for an hour.
The symptom
A new handset, freshly wiped, joining the same Wi-Fi network the other phones were sitting on. The network the host itself runs. Same SSID, same passphrase, pasted from the same place.
The phone's UI did what Android always does when a join fails: it fell back to
Check password and try again. In logcat it looked like this — a join
attempt, a refusal, and then nothing:
WifiNetworkSelector: connect-network
ClientModeImpl: rejoin FAILED
So we did the obvious things. Retyped the passphrase by hand rather than pasting it. Forgot the network and re-added it. Checked for a stray leading space in the stored PSK. Confirmed another phone could still join with the same credential — it could, immediately, which should have been the first real clue and instead read as "so the network is fine, it must be this handset."
We then spent a while on the handset. Different band, forget-all-networks, reset network settings, reboot. Same refusal every time.
The line that actually mattered
Turning up the Wi-Fi logs on the supplicant gave us the real event:
wpa_supplicant: ASSOC-REJECT status_code=1027
That single line relocates the problem, and it is worth being precise about why.
An 802.11 client joins in stages. It associates with the access point first,
and only then runs the 4-way handshake that proves it knows the passphrase.
Those are separate steps in that order. ASSOC-REJECT means the access point
refused at the first one — before the passphrase was presented, let alone
checked.
So whatever went wrong, the credential was never part of the conversation. Every minute we spent on the passphrase was spent on a step the phone never reached. Android's "check your password" message is a generic fallback for "association did not complete", and it is actively misleading here: it names the one thing that had definitively not failed.
If you take one thing from this post, take that. ASSOC-REJECT in the log and
wrong password on the screen are not consistent with each other, and the log
wins.
Why it was refused
The host's onboard radio was out of room.
An access point keeps a table of associated stations, and that table has a finite number of slots. Ours was full. The refusal was the access point saying so in the only way the protocol gives it, at the only point in the exchange where it can.
One command would have told us in about a second, and it is now the first thing we run:
iw dev wlan0 station dump | grep -c '^Station'
That prints the number of stations currently associated. Compare it to the number of devices you expect to be associated. If those two numbers disagree, stop looking at the new device — something else is holding a slot.
Which is exactly what had happened. One of the slots was not ours. A Redmi
handset belonging to nobody in the rack had attached to the network and was
quietly occupying a place in the table. We evicted it with a MAC deny entry
(deny_mac_file in the AP config), the slot freed, and the new phone
associated on the next attempt with no other change. Same passphrase we had
been retyping all along.
What we changed
Three things, in order of how much they were worth.
The station count is now the first diagnostic, not the last. Any "this
device won't join" report starts with station dump and a count, before anyone
touches a credential. It is one command and it either exonerates the network or
finds the problem outright.
The AP has an explicit deny list. A device that is not part of the rack should not be able to take a slot, and until this happened nothing stopped one. That is a small hardening job we had not thought to do because we had never hit the ceiling before — with room to spare, a squatter costs nothing and is invisible.
We accepted that one radio has a ceiling. This is the part with no clever fix. Growing past what the onboard radio will hold means a second radio, not a configuration flag. We would rather know that now, as a planning constraint, than discover it during a deploy.
Being honest about the numbers
We are deliberately not publishing "the limit is N" as a general fact, because it is not one. The number of stations an access point will hold depends on the chipset, the driver, the AP software and how it was configured — and the figure that gets quoted for consumer hardware is frequently not the figure you actually get. Ours was lower than we would have guessed, which is the entire reason this cost us an afternoon.
What generalises is not the number. It is the shape:
ASSOC-REJECTmeans the refusal happened before authentication, so the passphrase is not your problem no matter what the phone's UI says.- A full station table produces exactly this signature.
- The count of associated stations is cheap to check and is the fastest way to tell "this device is broken" from "this network is full".
- Something you do not own can be holding a slot.
Where this is not your bug
If the join fails after association — a 4-way handshake timeout, or an
explicit WRONG_KEY / AUTH_FAILED in the supplicant log — then it really can
be the credential, and this post does not apply to you. The distinction is
visible in the logs and nowhere else, which is the frustrating part: the one
screen every user looks at is the one that cannot tell you which case you are
in.
And if you are running a handful of devices against a home router with plenty of headroom, you will probably never meet this. It only shows up at the ceiling, and the ceiling is usually somewhere you were not expecting to find one.
We rent physical Android phones by the minute, which means we operate the rack these notes come out of. If you want a real handset over real ADB without running the hardware yourself, that is what DeviceRent is. If you are building your own lab, the design notes on the rack cover the rest of the constraints.
More from the workshop
September 13, 2026
Testing on Samsung One UI vs stock Android: what actually differs
The rack stopped being six identical Pixel 7a. Two Samsungs joined it, and the second Android is the part that matters — Settings layout, the default keyboard, twenty preinstalled packages, and a 32-bit ABI the Pixels cannot run.
September 2, 2026
Renting three phones at once: a feature the backend already had
We shipped multi-device rentals this week. The database had already enforced the limit for over a year — the only thing missing was a UI that let you click twice.
September 2, 2026
The phone that couldn't be cleaned: a dead end nobody could see
A phone can be marked available and still owe a wipe. When both were true at once it became unrentable and unwipeable at the same time — and nothing was watching for it.