Google Workspace OAuth disabled_client detection and live checks
Cluster 19570. Data as of
Nothing open on GitHub. Fix merged in #21826 on 8 May 2026. Check it covers your case.
The short answer
- Known?
- Yes. 3 related items grouped here, 1 issue already closed.
- Fix event
- A fix was merged to main in PR #21826. Check it covers your case. No release data is tracked.
- Tracker
- The maintainers' tracker marks this
resolved, deciding PR #21826. That is separate from the fix event. - Still open
- Nothing open on GitHub.
These issues and PRs address how the Google Workspace integration detects and reports disabled or misconfigured OAuth clients, including hardening the --check flow, adding a live-check mode, and correcting misclassification of partial-scope 403 errors as disabled-client errors.
Open issues0
Open PRs0
Fixes on record
-
#21826 fix(google-workspace): detect disabled_client in --check and add --check-live (salvage of #19643)
files:
scripts/release.py,skills/productivity/google-workspace/scripts/setup.pyShow the diff
-
scripts/release.py@@ -47,6 +47,7 @@ "[redacted:email]": "qiyin-code", "[redacted:email]": "olisikh", "[redacted:email]": "leoneparise", + "[redacted:email]": "ygd58", "[redacted:email]": "teknium1", "[redacted:email]": "thelumiereguy", "[redacted:email]": "counterposition", -
skills/productivity/google-workspace/scripts/setup.py@@ -130,7 +130,33 @@ def _ensure_deps(): sys.exit(1) -def check_auth(): +def check_auth_live(): + """Check auth with a real API call to detect disabled_client/account issues.""" + # quiet=True suppresses the "AUTHENTICATED" print from check_auth so the + # final status line reflects the live-call outcome (OK or FAILED). + if not check_auth(quiet=True): + return False + try: + from googleapiclient.discovery import build + from google.oauth2.credentials import Credentials + creds = Credentials.from_authorized_user_file(str(TOKEN_PATH)) + service = build("calendar", "v3", credentials=[redacted:secret-assignment] + service.calendarList().list(maxResults=1).execute() + print("LIVE_CHECK_OK: Real API call succeeded.") + return True + except Exception as e: + err_str = str(e).lower() + if "disabled_client" in err_str or "invalid_client" in err_str: + print(f"LIVE_CHECK_FAILED: OAuth client or account disabled: {e}") + print(" 1. Check Google Cloud Console for disabled OAuth client") + print(" 2. Check myaccount.google.com for account status") + print(" 3. Do NOT retry with a disabled account") + else: + print(f"LIVE_CHECK_FAILED: {e}") + return False + + +def check_auth(quiet: bool = False): """Check if stored credentials are valid. Prints status, exits 0 or 1.""" if not TOKEN_PATH.exists(): print(f"NOT_AUTHENTICATED: No token at {TOKEN_PATH}") @@ -157,7 +183,8 @@ def check_auth(): print(f"AUTHENTICATED (partial): Token valid but missing {len(missing_scopes)} scopes:") for s in missing_scopes: print(f" - {s}") - print(f"AUTHENTICATED: Token valid at {TOKEN_PATH}") + if not quiet: + print(f"AUTHENTICATED: Token valid at {TOKEN_PATH}") return True if creds.expired and creds.refresh_token: @@ -174,10 +201,25 @@ def check_auth(): print(f"AUTHENTICATED (partial): Token refreshed but missing {len(missing_scopes)} scopes:") for s in missing_scopes: print(f" - {s}") - print(f"AUTHENTICATED: Token refreshed at {TOKEN_PATH}") + if not quiet: + print(f"AUTHENTICATED: Token refreshed at {TOKEN_PATH}") return True except Exception as e: - print(f"REFRESH_FAILED: {e}") + err_str = str(e).lower() + if "disabled_client" in err_str or "invalid_client" in err_str: + print(f"OAUTH_CLIENT_DISABLED: {e}") + print(" The OAuth client or Google account has been disabled.") + print(" Steps to resolve:") + print(" 1. Check your Google Cloud Console — verify the OAuth client is not disabled") + print(" 2. Check if your Google account itself has been disabled at myaccount.google.com") + print(" 3. If the account is disabled, you can appeal at accounts.google.com/signin/recovery") + print(" 4. Do NOT retry API calls with a disabled account — this may worsen the situation") + print(" 5. If the OAuth client is disabled, create a new one in Google Cloud Console") + elif "token_revoked" in err_str or "invalid_grant" in err_str: + print(f"TOKEN_REVOKED: {e}") + print(" Re-run setup to re-authenticate.") + else: + print(f"REFRESH_FAILED: {e}") return False print("TOKEN_INVALID: [redacted:secret-assignment] setup.") @@ -384,6 +426,7 @@ def main(): parser = argparse.ArgumentParser(description="Google Workspace OAuth setup for Hermes") group = parser.add_mutually_exclusive_group(required=True) group.add_argument("--check", action="store_true", help="Check if auth is valid (exit 0=yes, 1=no)") + group.add_argument("--check-live", action="store_true", help="Check auth with a real API call (detects disabled_client)") group.add_argument("--client-secret", metavar="PATH", help="Store OAuth client_secret.json") group.add_argument("--auth-url", action="store_true", help="Print OAuth URL for user to visit") group.add_argument("--auth-code", metavar="CODE", help="Exchange auth code for token") @@ -393,6 +436,8 @@ def main(): if args.check: sys.exit(0 if check_auth() else 1) + if getattr(args, "check_live", False): + sys.exit(0 if check_auth_live() else 1) elif args.client_secret: [redacted:secret-assignment] elif args.auth_url:
-
1 PR closed without merging
From the close comments: merged via another change 1
-
#19643 fix(google-workspace): detect disabled_client in --check and add --check-live · merged via another change →
#21826
Closed issues · 1
- Closed#19570google-workspace: fresh Google account disabled shortly after official OAuth setup; setup.py --check still reports AUTHENTICATED while API call fails disabled_client
How this cluster was grouped
-
Link evidence (
structural links throughout): every member is connected by structural evidence: shared changed files, or a closing/superseded reference. -
Pairwise link density
0.67: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36.1.00means every pair is linked.
Pick up a Lab task
Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.
Open the LabAt a glance
- Merged PRs
- #21826
- Closed issues
- 1
- Attempts
- 1 PR closed without merging
- Fix link checked
- 8 May 2026