From a78d650d6f6987d078d1e2d28dfe15bd1e5a40e2 Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 14 May 2025 12:59:32 -0400 Subject: [PATCH] Enhance error handling in GitHubClient: improve JSON response parsing, handle non-JSON error responses, and implement retry logic for repository creation with minimal parameters. --- template_automation/github_client.py | 67 +++++++++++++++++++--------- 1 file changed, 47 insertions(+), 20 deletions(-) diff --git a/template_automation/github_client.py b/template_automation/github_client.py index 1a0d832..8ccc526 100644 --- a/template_automation/github_client.py +++ b/template_automation/github_client.py @@ -126,15 +126,26 @@ def _request(self, method: str, url: str, **kwargs) -> Dict[str, Any]: # Return JSON data for non-empty responses if response.text: - return response.json() + try: + return response.json() + except json.JSONDecodeError: + logger.warning(f"Received non-JSON response: {response.text}") + return {"raw_content": response.text} return {} except requests.exceptions.RequestException as e: if hasattr(e, 'response') and e.response is not None: try: - error_body = e.response.json() - logger.error(f"GitHub API error details: {json.dumps(error_body)}") - except (ValueError, json.JSONDecodeError): - logger.error(f"GitHub API error: {e.response.text}") + # Try to parse JSON, but handle case where response is not JSON + if e.response.text.strip(): + try: + error_body = e.response.json() + logger.error(f"GitHub API error details: {json.dumps(error_body)}") + except json.JSONDecodeError: + logger.error(f"GitHub API returned non-JSON error: {e.response.text}") + else: + logger.error(f"GitHub API returned empty error response with status code: {e.response.status_code}") + except (ValueError, AttributeError): + logger.error(f"GitHub API error: Unable to parse response") logger.error(f"Request failed: {str(e)}") raise @@ -174,25 +185,41 @@ def get_repository( # Try with minimal parameters first repo = self._request("POST", url, json={ "name": repo_name, - "private": False, + "private": True, "auto_init": True }) except requests.exceptions.HTTPError as create_error: - # Log detailed error information for 422 errors - if create_error.response.status_code == 422: - error_response = create_error.response.json() - logger.error(f"GitHub API error details: {json.dumps(error_response)}") - # Try again with even more minimal parameters if it's a schema validation issue - if "message" in error_response and "Validation Failed" in error_response.get("message", ""): - logger.info("Retrying repository creation with minimal parameters") - repo = self._request("POST", url, json={ - "name": repo_name, - "private": True - }) + # Safe handling of response parsing + error_message = str(create_error) + try: + if create_error.response.text.strip(): + try: + error_response = create_error.response.json() + logger.error(f"GitHub API error details: {json.dumps(error_response)}") + # Check for validation errors + if "message" in error_response and "Validation Failed" in error_response.get("message", ""): + logger.info("Retrying repository creation with minimal parameters") + repo = self._request("POST", url, json={ + "name": repo_name, + "private": True + }) + else: + raise create_error + except json.JSONDecodeError: + # Handle non-JSON responses + logger.error(f"GitHub API returned non-JSON error response: {create_error.response.text}") + # Try with most minimal parameters as a fallback + logger.info("Retrying repository creation with minimal parameters due to non-JSON error") + repo = self._request("POST", url, json={ + "name": repo_name, + "private": True + }) else: - raise - else: - raise + logger.error(f"Empty error response with status code: {create_error.response.status_code}") + raise create_error + except (AttributeError, ValueError) as parse_error: + logger.error(f"Error parsing response: {str(parse_error)}") + raise create_error # Wait for repository initialization max_retries = 10