infiniflow/ragflow · error · CredentialExpiredError

Moodle token is invalid or expired

Error message

Moodle token is invalid or expired

What it means

A CredentialExpiredError raised in load_credentials when constructing the MoodleClient and calling core.webservice.get_site_info() throws a MoodleException whose text contains 'invalidtoken'. The probe call doubles as credential verification; Moodle returns an invalidtoken error code when the token does not exist, was revoked, or expired.

Source

Thrown at common/data_source/moodle_connector.py:80

    def _get_latest_timestamp(self, *timestamps: int) -> int:
        """Return latest valid timestamp"""
        return max((t for t in timestamps if t and t > 0), default=0)

    def _yield_in_batches(self, generator: Generator[Document, None, None]) -> Generator[list[Document], None, None]:
        for batch in batch_generator(generator, self.batch_size):
            yield batch

    def load_credentials(self, credentials: dict[str, Any]) -> None:
        token = credentials.get("moodle_token")
        if not token:
            raise ConnectorMissingCredentialError("Moodle API token is required")

        try:
            self.moodle_client = MoodleClient(self.moodle_url + "/webservice/rest/server.php", token)
            self.moodle_client.core.webservice.get_site_info()
        except MoodleException as e:
            if "invalidtoken" in str(e).lower():
                raise CredentialExpiredError("Moodle token is invalid or expired")
            raise ConnectorMissingCredentialError(f"Failed to initialize Moodle client: {e}")

    def validate_connector_settings(self) -> None:
        if not self.moodle_client:
            raise ConnectorMissingCredentialError("Moodle client not initialized")

        try:
            site_info = self.moodle_client.core.webservice.get_site_info()
            if not site_info.sitename:
                raise InsufficientPermissionsError("Invalid Moodle API response")
        except MoodleException as e:
            msg = str(e).lower()
            if "invalidtoken" in msg:
                raise CredentialExpiredError("Moodle token is invalid or expired")
            if "accessexception" in msg:
                raise InsufficientPermissionsError("Insufficient permissions. Ensure web services are enabled and permissions are correct.")
            raise ConnectorValidationError(f"Moodle validation error: {e}")
        except Exception as e:

View on GitHub (pinned to 554fb1133a)

Solutions

  1. Issue a fresh token in Moodle (Manage tokens) and update the stored credential.
  2. Confirm the token belongs to the same Moodle site as moodle_url.
  3. Strip whitespace from the token before storing it.
  4. If tokens keep expiring, ask the Moodle admin to set a longer TTL or create a system-token for the service.

Example fix

# before
connector.load_credentials({'moodle_token': old_token})  # CredentialExpiredError: Moodle token is invalid or expired

# after
token = os.environ['MOODLE_TOKEN'].strip()
connector.load_credentials({'moodle_token': token})
Defensive patterns

Strategy: retry

Try / catch

try:
    connector.load_credentials({'moodle_token': token})
except CredentialExpiredError:
    token = request_new_moodle_token()  # admin/API re-issue
    connector.load_credentials({'moodle_token': token})

Prevention

When it happens

Trigger: Calling load_credentials with a token that Moodle rejects during the get_site_info handshake — deleted/expired token, token for a different site, or a token whose user was removed.

Common situations: Token TTL elapsed (Moodle tokens can be configured to expire); admin pruned tokens; token copied from another Moodle instance; trailing whitespace/newline pasted with the token.

Understand the failure class

Related errors


AI-assisted analysis of infiniflow/ragflow@554fb1133a (2026-08-15). Data as JSON: /api/errors/7eeef52d2578e075. Report an issue: GitHub.