logo
Development
Search
07 · Troubleshooting

07 · Troubleshooting

Master Error-Code Table

The WsaVerificationError.code Thrown by verifyWsa

code Common cause How to troubleshoot
InvalidSignature Wrong secret, tampered token, or the wrong Tier1/Tier2 secret used Confirm the backend uses the same secret as registered/distributed; pass the per-app secret in as the raw string, do not hex-decode it
WrongAudience audience does not match the token's aud audience must exactly equal the host of the registered URL (e.g., app.example.com), without the port/protocol
WrongIssuer The issuer configuration was changed Keep the default gptbots-workspace
Expired The token is over 5 minutes old, or the server clock is skewed NTP-sync the server clock; the wsa is a one-time bootstrap token, do not cache and reuse it
NotYetValid iat/nbf is in the future Usually the issuer/verifier clocks are severely out of sync
MissingClaim Missing exp/sub/role/workspace_id A normal platform token never lacks these; if it occurs, the token's origin is suspicious
UnsupportedAlgorithm alg is not in the allowlist By default only HS256; RS256 requires an explicit algorithms:['RS256'] + publicKey
InvalidToken The token is empty/structurally invalid/truncated Check whether the frontend correctly obtained the complete wsa and whether the URL was rewritten by an intermediate layer

The /token Exchange Phase (Pull)

code Meaning Trigger condition
403209 Invalid grant The code is missing, expired, or already used (replay). A code can only be used once
403210 Invalid verifier The PKCE codeVerifier does not match the code_challenge from initiation

Push sign-token (Called by the Workspace Frontend, for Awareness Only)

code Meaning Trigger condition
40000 Parameter error The URL is not on file, or auth_mode is not workspace_account
40100 Permission deny Not logged in or the session has expired
40105 Require member of project The clicker is not a member of this workspace
40320 Member not found The account was deactivated/deleted

FAQ

Q: Should I choose push or pull?
A: If the entry is in the workspace "Extensions" page and you want to build an "embedded app" → push (simplest). If your app is a standalone site and you want to place a "Sign in with GPTBots" button → pull (M-Auth, more secure, the wsa never enters the browser). See 02.

Q: Can I decode the JWT directly on the frontend to get user info?
A: You can decode it to look, but you cannot treat it as a trusted identity — without the secret you cannot verify the signature, and the payload can be forged. Any authorization decision must be based on the backend's verifyWsa result. See 05 §5.

Q: What do I do when the wsa expires?
A: The wsa is just a one-time bootstrap token (5 minutes). Verify it once on landing, exchange it for your own session, and use your session thereafter — do not depend on the wsa again. The next time the user opens the app from the extensions page, they will receive a fresh wsa.

Q: The landing page's consumeHandoff throws "no handoff token present"?
A: This means the current URL has no ?wsa= — possibly the user accessed directly, or the wsa was already stripped by a previous successful exchange. Distinguish "first landing with a token" from "an ordinary visit"; for the latter, go to your own login/anonymous branch.

Q: Pull login callback reports StateMismatch / MissingRequest?
A: MissingRequest = startWorkspaceLogin was not called first in the same browser session (the PKCE verifier is stored in sessionStorage, and it is lost if you switch tabs or clear storage). StateMismatch = the callback state does not match the stored one (CSRF protection); make sure you are not going across devices/sessions.

Q: Pull login reports CryptoUnavailable?
A: PKCE requires Web Crypto, which is only available in a secure context (HTTPS or localhost). Use HTTPS or debug locally on localhost.

Q: redirect_uri reports invalid_request / returns to the organization selection page?
A: The redirect_uri's scheme + host must exactly match client_id (the registered URL). An https app cannot configure an http callback; the host must match. The platform never redirects to an unverified address, so it returns to the organization selection page with ?error=invalid_request.

Q: How do I use the per-app secret as the HMAC key? Do I need to base64/hex-decode it?
A: Pass it in as the raw string (both the SDK and the platform use the UTF-8 bytes directly as the HMAC key). A Tier 2 secret looks like wext_+64 hex; the whole string is the secret, do not decode it.

Q: Can CommonJS projects use the SDK?
A: The SDK is ESM. CJS projects should use a dynamic import() or convert the relevant modules to ESM.

Q: How do I change the icon/name?
A: Tier 2: edit it in Space Management; Tier 1: contact platform operations to change the dictionary entry.

Q: What happens if an admin disables my app?
A: An organization admin can disable an app in Space Management (including the visibility of a platform public app within this organization). After disabling, members of that organization will no longer see the entry on the extensions page, and the platform will no longer issue a wsa for that organization (both push and pull are refused).

Debugging Checklist

  • audience == the host of the registered URL (the most common source of WrongAudience)
  • The backend secret matches what was registered/distributed, and is kept only on the backend
  • The server clock is NTP-synced (Expired / NotYetValid are mostly due to the clock)
  • history.replaceState to strip wsa / code after landing
  • Exchange for your own session; subsequent requests do not pass through the wsa
  • Pull: an HTTPS/localhost secure context; redirect_uri same-origin as client_id
  • Multi-tenant isolation by workspace_id

References