Troubleshooting & FAQ¶
"Node.js not found" / REQUEST_INVALID_HMAC (code 10005)¶
Every request needs the X-Hmac signature, computed by Node + ltsm.wasm.
- Install Node.js 18+ and make sure
node --versionworks in the same shell. - Non-standard path?
set LINE_NODE=C:\path\to\node.exe(Windows) /export LINE_NODE=/path/to/node, orOkLine(config=LineConfig(node_path="...")). - For offline unit tests only, you can disable signing with
OkLine(config=LineConfig(enable_hmac=False))(requests will then be rejected by the real server — this is for mocked tests).
okline: command not found¶
The okline script is installed into your Python environment's Scripts/
(Windows) or bin/ (macOS/Linux) directory. If your shell can't find it:
- Run the module form instead — it always works:
- Or add the Scripts/bin directory to your
PATH. On Windows it's usually...\PythonXX\Scripts(or the venv'sScripts);pip show -f oklinelists where the script landed.
[encrypted] messages / can't read Letter-Sealed text¶
If a received message shows up as [encrypted] (or its text is empty while it
has a chunks field), your E2EE keys aren't loaded.
- Log in once so the keychain is captured and saved:
This writes
./tokens.jsonincluding the E2EE keychain; later runs reuse it automatically. - In code, reuse that session and check readiness:
- If
is_ready()isFalse, the keychain wasn't loaded — re-runokline login(scan QR → confirm PIN) to refresh it. E2EE keys load duringqr_loginand persist viasave_tokens/from_tokens_file. - If only your own sent messages show
[encrypted]while the other side decrypts fine, you are on a version before 2.7.1 — own-message decryption was fixed there; upgrade and re-run the command.
The phone shows "an error occurred" after scanning the QR¶
The QR must carry ?secret=<curve25519 pubkey>&e2eeVersion=1. OkLine adds this
automatically in auth.qr_login — make sure you render the URL passed to your
on_qr callback (not some other URL), and that you're on a current version.
The QR is unreadable in the terminal¶
- Light-background terminal:
print_qr(url, invert=True). - Windows console garbling the blocks: run
chcp 65001first, or use Windows Terminal / PowerShell 7. - Make it bigger:
print_qr(url, style="full")(double width). - No inline QR at all? Install the optional extra:
pip install "okline[qr]".
UnicodeEncodeError / garbled non-ASCII (Thai, emoji, …)¶
The CLI already forces UTF-8 output, so okline ... prints non-ASCII text
correctly. In your own scripts, a legacy console encoding (e.g. Windows
cp1252) can still raise UnicodeEncodeError. Fix it once at startup:
or set the environment variable before launching Python:
api.print_last() is already UTF-8 safe and degrades gracefully on a console
that can't encode a character.
A response is None or a key is missing (KeyError)¶
The gateway wraps results as {"message":"OK","data":...}; OkLine unwraps
.data. If you call the transport very directly you may see the envelope. Turn
on raw logging to see exactly what came back:
A non-OK envelope is raised as LineApiError (with .code, .reason).
getChats / getContacts — Invalid Length (code 6)¶
The gateway rejects more than 100 mids in one getChats/getContactsV2 call.
OkLine now auto-chunks these requests at 100 mids and merges the results, so
you can pass arbitrarily long lists. If you still hit this, upgrade to the
latest version (pip install -U okline).
401 / token expired¶
- Pass a
refresh_tokenso OkLine auto-refreshes:OkLine(access_token=..., refresh_token=...). - The gateway usually signals credential expiry with TalkException code 119
(
MUST_REFRESH_V3_TOKEN), not HTTP 401. OkLine detects 119, renews the access token via the refresh hook (same path as 401) and replays the request once automatically — no caller action needed. - Or refresh manually:
api.auth.refresh_access_token(). - If you loaded the client with
OkLine.from_tokens_file(...), the refreshed token is written back to the session file automatically. - If the session was revoked (logged out on another device), log in again
(
okline login).
LineAuthError on refresh — 10201 / 10202 (tokenRefresh codes)¶
The /api/auth/tokenRefresh endpoint answers with its own gateway envelope
codes (the qU family), not TalkException codes:
- 10201
AUTH_INVALID_REQUEST— a hard kickout: the refresh token is no longer valid (session revoked / logged out elsewhere). OkLine raisesLineAuthError("token refresh rejected (AUTH_INVALID_REQUEST): re-login required"). Nothing recovers from this — log in again (okline login). - 10202
AUTH_RETRY_REQUIRED— the server is temporarily unwilling to refresh and asks the client to retry.refresh_access_token()retries with the server-providedrefreshApiRetryPolicy(jittered exponential backoff, capped atmaxDelayInMillis) — see Token refresh. If the retries are exhausted you get aLineAuthError; wait and refresh again, and considerOkLine(..., auto_refresh_schedule=True)so renewal happens proactively before the token goes stale.
LineMustUpgradeError / REQUEST_MUST_UPGRADE¶
The server wants a newer client version. The trigger is the outer envelope
code 10006 (REQUEST_MUST_UPGRADE). The bundled app version is 3.7.2; if
LINE forces an upgrade you may need a newer ltsm.wasm + version string from a
fresh extension build (LineConfig(app_version=...), ltsm_origin=...).
Transient errors retried automatically (99999 / 115)¶
OkLine retries a request within the configured retry budget
(LineConfig(max_retries=...), default 2) when the outer envelope code is
99999 (UNKNOWN_ERROR) or the nested TalkException code is 115
(SHOULD_RETRY) — matching the extension's axios retry condition — in addition
to HTTP 5xx and network failures. If you still see these surface, the retries
were exhausted; wait and retry your call.
Reading errors¶
from okline import LineApiError, enums
try:
api.send_text(to, "hi")
except LineApiError as e:
print(e.code, e.reason, e.metadata)
# map a numeric code to a name:
print(enums.ErrorCode(e.code).name if e.code is not None else "?")
Common ErrorCodes: AUTHENTICATION_FAILED(1), NOT_AVAILABLE_USER(7),
NOT_AUTHORIZED_DEVICE(8), NOT_FRIEND(36), MUST_UPGRADE(50),
EXPIRED_REVISION(52), MUST_REFRESH_V3_TOKEN(119). Codes 1/7/8 raise
LineAuthError (re-login required; 119 is auto-refreshed first — see
token expired). Full list in
okline/enums.py.
Long-poll / SSE seems to hang¶
That's expected — iter_operations() and the verify long-polls block until
something happens or the server times out. Use a thread, or set
qr_login(wait_seconds=...).
Rate limits / abuse blocks¶
EXCESSIVE_ACCESS(4), ABUSE_BLOCK(35), CONGESTION_CONTROL(58) mean you're
sending too fast or tripping anti-abuse. Slow down and only use your own
account. You can pace requests automatically with the built-in token bucket:
from okline.ratelimit import RateLimiter
api.transport.rate_limiter = RateLimiter(rate=5, per=1.0) # ~5 req/s
Still stuck?¶
Capture a redacted transcript and inspect it:
See recording for the full transcript/HAR options.