{"record":{"id":"fc8d7fa3a4205bf2","repo":"infiniflow/ragflow","slug":"insufficient-permissions-ensure-web-services-are","errorCode":null,"errorMessage":"Insufficient permissions. Ensure web services are enabled and permissions are correct.","messagePattern":"Insufficient permissions\\. Ensure web services are enabled and permissions are correct\\.","errorType":"validation","errorClass":"InsufficientPermissionsError","httpStatus":null,"severity":"error","filePath":"common/data_source/moodle_connector.py","lineNumber":96,"sourceCode":"        except MoodleException as e:\n            if \"invalidtoken\" in str(e).lower():\n                raise CredentialExpiredError(\"Moodle token is invalid or expired\")\n            raise ConnectorMissingCredentialError(f\"Failed to initialize Moodle client: {e}\")\n\n    def validate_connector_settings(self) -> None:\n        if not self.moodle_client:\n            raise ConnectorMissingCredentialError(\"Moodle client not initialized\")\n\n        try:\n            site_info = self.moodle_client.core.webservice.get_site_info()\n            if not site_info.sitename:\n                raise InsufficientPermissionsError(\"Invalid Moodle API response\")\n        except MoodleException as e:\n            msg = str(e).lower()\n            if \"invalidtoken\" in msg:\n                raise CredentialExpiredError(\"Moodle token is invalid or expired\")\n            if \"accessexception\" in msg:\n                raise InsufficientPermissionsError(\"Insufficient permissions. Ensure web services are enabled and permissions are correct.\")\n            raise ConnectorValidationError(f\"Moodle validation error: {e}\")\n        except Exception as e:\n            raise ConnectorValidationError(f\"Unexpected validation error: {e}\")\n\n    # -------------------------------------------------------------------------\n    # Data loading & polling\n    # -------------------------------------------------------------------------\n\n    def load_from_state(self) -> Generator[list[Document], None, None]:\n        if not self.moodle_client:\n            raise ConnectorMissingCredentialError(\"Moodle client not initialized\")\n\n        logger.info(\"Starting full load from Moodle workspace\")\n        courses = self._get_enrolled_courses()\n        if not courses:\n            logger.warning(\"No courses found to process\")\n            return\n","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/infiniflow/ragflow/blob/554fb1133ac3861732235ad9c377eb5e0a770665/common/data_source/moodle_connector.py#L78-L114","documentation":"An InsufficientPermissionsError raised in validate_connector_settings when the get_site_info() MoodleException text contains 'accessexception'. Moodle returns this error code when the authenticated user's role lacks the webservice/webservice:createtoken capability scope or web services are disabled at site level, so the call is rejected before any data flows.","triggerScenarios":"Calling validate_connector_settings() where the token's user cannot use web services — web services disabled in Site administration, user role missing required capabilities, or token created for a service the user is not enrolled in.","commonSituations":"Moodle admin has not enabled 'Enable web services' / 'Enable REST protocol'; token user is a student-level account; token bound to a custom service lacking functions; fresh Moodle install without web service setup.","solutions":["In Moodle: Site administration > Plugins > Web services > Overview — enable web services and the REST protocol.","Ensure the token user's role has the needed capabilities (webservice/webservice:use, plus the functions in the token's service such as core_course_get_courses).","Recreate the token selecting the correct service (or default 'all functions' for admins) and revalidate."],"exampleFix":"# before: token bound to a limited service, validation raises InsufficientPermissionsError\nconnector.validate_connector_settings()\n\n# after: admin creates token on a service that includes core_webservice_get_site_info,\n# core_course_get_courses, core_course_get_contents; then\nconnector.load_credentials({'moodle_token': new_token})\nconnector.validate_connector_settings()","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    connector.validate_connector_settings()\nexcept InsufficientPermissionsError as exc:\n    notify_admin_to_enable_web_services(str(exc))  # actionable, config-side fix required","preventionTips":["Before creating the connector, have the Moodle admin complete the web-services setup checklist (enable web services + REST protocol).","Create tokens from a service that includes the required functions."],"tags":["moodle","permissions","web-services","validation","configuration"],"backgroundTag":null,"analyzedSha":"554fb1133ac3861732235ad9c377eb5e0a770665","analyzedAt":"2026-08-15T09:20:16.380Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}