What happens
Rohlík's login endpoint can answer with status: 202 instead of 200, with no message and no session:
{"status": 202, "messages": [], "data": null}
AuthManager.login() collapses every non-200, non-401 body status into the base RohlikAPIError, and because messages is empty the message degenerates to a tautology:
RohlikAPIError("Unknown error occurred during login: Unknown error")
The status code (202) and the response body are dropped, and nothing is logged. A consumer cannot tell this apart from a genuine server error, and the field report carries no usable information.
What 202 appears to mean
Rohlík's own login page (/uzivatel/prihlaseni) ships these strings:
"Pro dokončení přihlášení klikněte na odkaz, který jsme vám poslali na adresu {{email}}"
"Zbývá jen potvrdit e-mail"
Their route table also has magicLink → /magic-login/keep-account, verificationEmail → /verification/email, plus Google/Apple/Facebook login callbacks.
That is exactly HTTP 202 Accepted semantics for a login: the request was accepted, but the login is not complete until the user clicks a link Rohlík e-mails them, so no session is issued. messages is empty because it is not an error — the web app switches to a "confirm your e-mail" screen off the status code alone. The keep-account magic-link route suggests this also covers accounts tied to a social login.
Worth stating plainly: this is inferred from their frontend, not from documentation, and I have not observed a 202 myself (it needs an account in that state). What is verified is that the client's request shape is not the cause — a cookie-less POST with the default rohlik-api-python/<ver> User-Agent and a non-existent e-mail returns a clean 401 with messageCode: login.invalid_credentials, so there is no anti-bot gate on this endpoint.
Why it matters
A consumer (e.g. the Home Assistant integration) currently has to report "unknown error" or "cannot connect" for what is really "go click the link in your inbox, then retry". It also cannot decide whether to retry the request (pointless here) or to ask the user to act.
Proposal
- Add a dedicated exception for the incomplete-login case, e.g.
LoginNotCompletedError(RohlikAPIError), raised when the login body status is 202.
- Carry the API status on the error so consumers can branch on codes this library does not yet know about — e.g. an optional
status: int | None attribute on RohlikAPIError (or at minimum include the numeric status in the message).
- Log the failing login body at debug through the existing
mask_data helper, and include the status in the exception message, so a field report is diagnosable:
RohlikAPIError("Login failed with status 202: <detail>").
While in there: login()'s docstring advertises APIRequestFailedError for a failed login request, but the body-status path raises the bare RohlikAPIError — worth aligning the docstring with the behaviour (and making the raised types explicit) as part of this change.
Downstream consumer issue: dvejsada/HA-RohlikCZ#86. Original user report: dvejsada/HA-RohlikCZ#79.
What happens
Rohlík's login endpoint can answer with
status: 202instead of200, with no message and no session:{"status": 202, "messages": [], "data": null}AuthManager.login()collapses every non-200, non-401 body status into the baseRohlikAPIError, and becausemessagesis empty the message degenerates to a tautology:The status code (
202) and the response body are dropped, and nothing is logged. A consumer cannot tell this apart from a genuine server error, and the field report carries no usable information.What 202 appears to mean
Rohlík's own login page (
/uzivatel/prihlaseni) ships these strings:Their route table also has
magicLink→/magic-login/keep-account,verificationEmail→/verification/email, plus Google/Apple/Facebook login callbacks.That is exactly HTTP 202 Accepted semantics for a login: the request was accepted, but the login is not complete until the user clicks a link Rohlík e-mails them, so no session is issued.
messagesis empty because it is not an error — the web app switches to a "confirm your e-mail" screen off the status code alone. Thekeep-accountmagic-link route suggests this also covers accounts tied to a social login.Worth stating plainly: this is inferred from their frontend, not from documentation, and I have not observed a 202 myself (it needs an account in that state). What is verified is that the client's request shape is not the cause — a cookie-less POST with the default
rohlik-api-python/<ver>User-Agent and a non-existent e-mail returns a clean401withmessageCode: login.invalid_credentials, so there is no anti-bot gate on this endpoint.Why it matters
A consumer (e.g. the Home Assistant integration) currently has to report "unknown error" or "cannot connect" for what is really "go click the link in your inbox, then retry". It also cannot decide whether to retry the request (pointless here) or to ask the user to act.
Proposal
LoginNotCompletedError(RohlikAPIError), raised when the login body status is202.status: int | Noneattribute onRohlikAPIError(or at minimum include the numeric status in the message).mask_datahelper, and include the status in the exception message, so a field report is diagnosable:RohlikAPIError("Login failed with status 202: <detail>").While in there:
login()'s docstring advertisesAPIRequestFailedErrorfor a failed login request, but the body-status path raises the bareRohlikAPIError— worth aligning the docstring with the behaviour (and making the raised types explicit) as part of this change.Downstream consumer issue: dvejsada/HA-RohlikCZ#86. Original user report: dvejsada/HA-RohlikCZ#79.