Skip to content

Better error handling#6

Open
yhurynovich wants to merge 6 commits into
ForgetMeAI:mainfrom
yhurynovich:main
Open

Better error handling#6
yhurynovich wants to merge 6 commits into
ForgetMeAI:mainfrom
yhurynovich:main

Conversation

@yhurynovich

Copy link
Copy Markdown

Summary
Two bugs in the browser-based Z.ai auth flow, both causing the script to fail without a usable error message.

  1. Script silently did nothing when invoked with a relative path
    The ESM "am I the entry point?" guard compared import.meta.url against a naive string concat of process.argv[1]:
    jsif (import.meta.url === file://${process.argv[1]}) { ... }
    import.meta.url is always an absolute, normalized file:// URL, but process.argv[1] is whatever was typed on the command line. Any relative invocation (node scripts/zai_browser_auth.js, as used by the npm run auth:browser script) — or any Windows path (backslashes, drive-letter encoding) — fails this comparison. main() was never called, and the process exited cleanly with zero output: no browser window, no error, nothing.
    Fixed by comparing against pathToFileURL(process.argv[1]).href instead of string concatenation. Also added an opt-in ZAI_AUTH_DEBUG_ENTRY=1 env var that prints the actual vs. expected URLs if this check ever fails again, to make this class of bug diagnosable next time.
  2. Crash on the execution-context-destroyed race right after login
    The polling loop calls page.evaluate(...) (via readToken) every 2s to check localStorage for a token. The moment the user finishes logging in, z.ai navigates/redirects, which can destroy the page's JS execution context mid-evaluate. Puppeteer throws Execution context was destroyed, most likely because of a navigation, which was unhandled and killed the whole process right as auth was about to succeed.
    Fixed by catching this (and a few sibling Puppeteer errors — target/session closed, detached frame) around the readToken call and treating them as "retry next tick" rather than fatal, since the next iteration gets a fresh valid context.

…teViaUi(); Fix — make sure the timer/listener always gets torn down, even if submission fails, so nothing is left ticking unattended:
Now when glm-5-deepresearch is used, the Z.ai API will receive deep_research: true in the features payload, enabling the deep research mode alongside web
search.
Root cause: KimiProvider.complete() was building the request with chat_id: session.providerSessionId || '' and message.parent_id: session.parentMessageId || ''. On a brand new session — which is every session after a container restart, since SessionStore is just an in-memory Map that resets on process start — this sends an explicit empty string "" for parent_id.

Compare to zai.js, which handles the same "no prior message" case with null instead of ''. Kimi's backend apparently treats an explicit "" as a real message ID it should look up rather than "no parent," so it comes back with REASON_CHAT_MESSAGE_NOT_FOUND — which matches the error text exactly (it's a message lookup failure, not a chat lookup failure, which is why chat_id alone wasn't the suspect).

Fix: only set chat_id / parent_id on the payload when there's an actual prior value; omit the fields entirely for a fresh conversation instead of sending
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant