8b1cdafd019d4adcad11a6712f48549b0460f1fa lrnassar Tue Jul 14 10:31:16 2026 -0700 Fix codeReviewAi.py false auth-failure on reviews that quote error strings. refs #36890 detect_cli_failure scanned the whole CLI response for auth-error markers before validating, so a well-formed review whose text legitimately quotes strings like "authentication_error" or "API Error: 401" (e.g. a review of the auth-handling code itself) was misflagged as a Claude CLI authentication failure - skipping the author email and firing a spurious alert. Validate the response first and only scan for auth markers when it is not a valid review. diff --git src/utils/codeReviewAi.py src/utils/codeReviewAi.py index e8acc71abad..9a0dadd1d72 100755 --- src/utils/codeReviewAi.py +++ src/utils/codeReviewAi.py @@ -497,38 +497,42 @@ # failed to produce a usable review. Used to alert instead of failing silently. CLI_AUTH_ERROR_MARKERS = ( 'Failed to authenticate', 'authentication_error', 'Invalid authentication credentials', 'API Error: 401', ) def detect_cli_failure(response, validator): """Return an error description if the CLI response indicates a hard failure (no output, an authentication error, or output that fails validation), otherwise return None. Lets the caller alert rather than silently save a broken review.""" if not response: return "No response from Claude CLI (timeout, crash, or empty output)" + # A well-formed review is a success even when its text quotes auth-error + # strings - e.g. a review of the auth-handling code itself. Only scan for + # auth markers when the output is NOT a valid review, so such reviews are + # not misflagged as authentication failures. + is_valid, msg = validator(response) + if is_valid: + return None for marker in CLI_AUTH_ERROR_MARKERS: if marker in response: first_line = next((l for l in response.strip().splitlines() if l.strip()), response) return f"Claude CLI authentication failure: {first_line.strip()[:300]}" - is_valid, msg = validator(response) - if not is_valid: return f"Invalid or incomplete review output: {msg}" - return None def call_claude_cli(prompt, timeout=600, retries=1, validator=None): """Call Claude Code CLI with a prompt and return the response""" if validator is None: validator = validate_review_output for attempt in range(retries + 1): try: result = subprocess.run( [CLAUDE_CLI, '-p', prompt, '--output-format', 'text', '--allowedTools', 'Bash,Read,Glob,Grep,Agent'], capture_output=True, text=True, timeout=timeout )