{"record":{"id":"4117baca34570dd1","repo":"infiniflow/ragflow","slug":"validation-failed-due-to-github-rate-limits-being","errorCode":null,"errorMessage":"Validation failed due to GitHub rate-limits being exceeded. Please try again later.","messagePattern":"Validation failed due to GitHub rate-limits being exceeded\\. Please try again later\\.","errorType":"validation","errorClass":"UnexpectedValidationError","httpStatus":null,"severity":"warning","filePath":"common/data_source/github/connector.py","lineNumber":738,"sourceCode":"                    if MISSING_SSO_ERROR_MESSAGE in str(e).lower():\n                        SSO_GUIDE_LINK = (\n                            \"https://docs.github.com/en/enterprise-cloud@latest/authentication/\"\n                            \"authenticating-with-saml-single-sign-on/\"\n                            \"authorizing-a-personal-access-token-for-use-with-saml-single-sign-on\"\n                        )\n                        raise ConnectorValidationError(\n                            f\"Your GitHub token is missing authorization to access the `{self.repo_owner}` organization. Please follow the guide to authorize your token: {SSO_GUIDE_LINK}\"\n                        )\n                    # If not an org, try as a user\n                    user = self.github_client.get_user(self.repo_owner)\n\n                    # Check if we can access any repos\n                    total_count = user.get_repos().totalCount\n                    if total_count == 0:\n                        raise ConnectorValidationError(f\"Found no repos for user: {self.repo_owner}. Does the credential have the right scopes?\")\n\n        except RateLimitExceededException:\n            raise UnexpectedValidationError(\"Validation failed due to GitHub rate-limits being exceeded. Please try again later.\")\n\n        except GithubException as e:\n            if e.status == 401:\n                raise CredentialExpiredError(\"GitHub credential appears to be invalid or expired (HTTP 401).\")\n            elif e.status == 403:\n                raise InsufficientPermissionsError(\"Your GitHub token does not have sufficient permissions for this repository (HTTP 403).\")\n            elif e.status == 404:\n                if self.repositories:\n                    if \",\" in self.repositories:\n                        raise ConnectorValidationError(f\"None of the specified GitHub repositories could be found for owner: {self.repo_owner}\")\n                    else:\n                        raise ConnectorValidationError(f\"GitHub repository not found with name: {self.repo_owner}/{self.repositories}\")\n                else:\n                    raise ConnectorValidationError(f\"GitHub user or organization not found: {self.repo_owner}\")\n            else:\n                raise ConnectorValidationError(f\"Unexpected GitHub error (status={e.status}): {e.data}\")\n\n        except Exception as exc:","sourceCodeStart":720,"sourceCodeEnd":756,"githubUrl":"https://github.com/infiniflow/ragflow/blob/554fb1133ac3861732235ad9c377eb5e0a770665/common/data_source/github/connector.py#L720-L756","documentation":"UnexpectedValidationError raised when any GitHub probe inside validate_connector_settings() hits RateLimitExceededException. It is deliberately a different class from ConnectorValidationError: rate limiting says nothing about whether the settings are correct, so callers should treat it as transient and retry rather than reject the config.","triggerScenarios":"Unauthenticated or secondary-rate limits tripped during validation — get_repo/get_contents/get_organization calls — typically when the same token runs frequent validations, CI loops, or indexing concurrently.","commonSituations":"Shared CI token across many jobs; validation retried in a tight loop; token already exhausted by a large indexing run; GitHub secondary rate limits from bursty API use.","solutions":["Wait for the rate-limit window to reset (check X-RateLimit-Reset / gh api rate_limit) and validate again.","Reduce validation frequency — cache the 'valid' verdict instead of revalidating each save.","Use a token with a higher limit (GitHub App installation tokens: 15k req/hr) and avoid parallel validations with the same token."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"rl = gh.get_rate_limit().core\nif rl.remaining == 0:\n    wait_until(rl.reset.timestamp())","typeGuard":null,"tryCatchPattern":"for attempt in range(3):\n    try:\n        connector.validate_connector_settings()\n        break\n    except UnexpectedValidationError:\n        time.sleep(2 ** attempt)  # rate limit is transient; settings may be fine","preventionTips":["Cache successful validation results instead of revalidating on every save.","Deduplicate concurrent validations sharing one token; check rate_limit before probing."],"tags":["github","rate-limit","transient","validation"],"backgroundTag":null,"analyzedSha":"554fb1133ac3861732235ad9c377eb5e0a770665","analyzedAt":"2026-08-15T09:20:16.380Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}