{"record":{"id":"4709ba641d90fadd","repo":"infiniflow/ragflow","slug":"box","errorCode":null,"errorMessage":"Box","messagePattern":"Box","errorType":"validation","errorClass":"ConnectorMissingCredentialError","httpStatus":null,"severity":"error","filePath":"common/data_source/box_connector.py","lineNumber":31,"sourceCode":"from common.data_source.interfaces import LoadConnector, PollConnector, SecondsSinceUnixEpoch\nfrom common.data_source.models import Document, GenerateDocumentsOutput, GenerateSlimDocumentOutput, SlimDocument\nfrom common.data_source.utils import get_file_ext\n\n\nclass BoxConnector(LoadConnector, PollConnector):\n    def __init__(self, folder_id: str, batch_size: int = INDEX_BATCH_SIZE, use_marker: bool = True) -> None:\n        self.batch_size = batch_size\n        self.folder_id = \"0\" if not folder_id else folder_id\n        self.use_marker = use_marker\n        self.box_client: BoxClient | None = None\n\n    def load_credentials(self, auth: Any):\n        self.box_client = BoxClient(auth=auth)\n        return None\n\n    def validate_connector_settings(self):\n        if self.box_client is None:\n            raise ConnectorMissingCredentialError(\"Box\")\n\n        try:\n            self.box_client.users.get_user_me()\n        except Exception as e:\n            logging.exception(\"[Box]: Failed to validate Box credentials\")\n            raise ConnectorValidationError(f\"Unexpected error during Box settings validation: {e}\")\n\n    def _iter_files_recursive(\n        self,\n        folder_id: str,\n        relative_folder_path: str = \"\",\n    ) -> Generator[tuple[Any, str], None, None]:\n        if self.box_client is None:\n            raise ConnectorMissingCredentialError(\"Box\")\n\n        result = self.box_client.folders.get_folder_items(\n            folder_id=folder_id,\n            limit=self.batch_size,","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/infiniflow/ragflow/blob/554fb1133ac3861732235ad9c377eb5e0a770665/common/data_source/box_connector.py#L13-L49","documentation":"Raised by BoxConnector.validate_connector_settings when self.box_client is None, i.e. load_credentials(auth) was never called. Unlike most connectors, Box auth is passed as an already-built BoxSDK auth object (e.g. BoxOAuth, BoxJWTAuth, or CCG auth), and load_credentials wraps it in a BoxClient. The message 'Box' identifies the connector whose credentials were not loaded.","triggerScenarios":"Constructing BoxConnector(folder_id) and calling validate_connector_settings() before load_credentials(auth); or the orchestration flow that should build the BoxSDK auth object (OAuth token from the redirect flow, JWT/CCG service account) failed silently upstream.","commonSituations":"Onyx indexing worker for the Box connector started without completing the OAuth flow or without the JWT/CCG secrets (client id/secret, enterprise id, keypair); test harnesses building the connector directly; credential refresh path that replaces the auth object but never reassigns box_client.","solutions":["Build a BoxSDK auth object (CCG: BoxCCGAuth(BoxClientAuth(...)); JWT: BoxJWTAuth; OAuth: BoxOAuth) and call load_credentials(auth) before validating","Verify the auth prerequisites exist: client_id, client_secret, and enterprise id (CCG) or a signed JWT keypair","Ensure the OAuth access token in the auth object is fresh — expired tokens fail later at get_user_me, not here","Fix orchestration ordering: load_credentials -> validate_connector_settings"],"exampleFix":"// before\nconnector = BoxConnector(folder_id='12345')\nconnector.validate_connector_settings()  # raises\n// after\nfrom boxsdk import CCGAuth, Client as BoxSdkClient\nccg = CCGAuth(client_id=cid, client_secret=csec, enterprise_id=eid)\nconnector = BoxConnector(folder_id='12345')\nconnector.load_credentials(auth=ccg)\nconnector.validate_connector_settings()","handlingStrategy":"validation","validationCode":"if connector.box_client is None:\n    raise RuntimeError('call load_credentials(auth) with a BoxSDK auth object first')\nconnector.validate_connector_settings()","typeGuard":"def is_box_ready(c: BoxConnector) -> bool:\n    return c.box_client is not None","tryCatchPattern":"from common.data_source.exceptions import ConnectorMissingCredentialError\ntry:\n    connector.validate_connector_settings()\nexcept ConnectorMissingCredentialError:\n    report('Box auth not configured — complete OAuth or provide CCG/JWT secrets')","preventionTips":["Build the BoxSDK auth object in one factory (CCG for server apps, OAuth for user apps) and pair it with load_credentials in the same setup function","Treat a missing/failed auth build as fatal in the orchestrator — BoxConnector methods all assume box_client exists"],"tags":["box","credentials","lifecycle","validation"],"backgroundTag":null,"analyzedSha":"554fb1133ac3861732235ad9c377eb5e0a770665","analyzedAt":"2026-08-15T09:20:16.380Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}