infiniflow/ragflow · error · Error

main() must be defined or exported.

Error message

main() must be defined or exported.

What it means

Thrown from validate_connector_settings when python-gitlab's auth() or projects.get() raises GitlabAuthenticationError. The GitLab Personal Access Token (PAT) is invalid, revoked, or the account it belonged to no longer authenticates. It maps to CredentialExpiredError so the backend can prompt for credential refresh.

Source

Thrown at agent/sandbox/result_protocol.py:46

if __name__ == "__main__":
    import base64
    import json

    result = main(**{args_json})
    payload = json.dumps({{"present": True, "value": result, "type": "json"}}, ensure_ascii=False, separators=(",", ":"))
    print("{RESULT_MARKER_PREFIX}" + base64.b64encode(payload.encode("utf-8")).decode("ascii"))
'''


def build_javascript_wrapper(code: str, args_json: str) -> str:
    return f"""{code}

const __ragflowArgs = {args_json};

(async () => {{
  const __ragflowMain = typeof main !== 'undefined' ? main : module.exports && module.exports.main;
  if (typeof __ragflowMain !== 'function') {{
    throw new Error('main() must be defined or exported.');
  }}
  const output = await Promise.resolve(__ragflowMain(__ragflowArgs));
  if (typeof output === 'undefined') {{
    throw new Error('main() must return a value. Use null for an empty result.');
  }}
  const payload = JSON.stringify({{ present: true, value: output, type: 'json' }});
  if (typeof payload === 'undefined') {{
    throw new Error('main() returned a non-JSON-serializable value.');
  }}
  console.log('{RESULT_MARKER_PREFIX}' + Buffer.from(payload, 'utf8').toString('base64'));
}})();
"""


def extract_structured_result(stdout: str) -> tuple[str, dict[str, Any]]:
    if not stdout:
        return "", {}

View on GitHub (pinned to 554fb1133a)

Solutions

  1. Verify the PAT still works: curl -H 'PRIVATE-TOKEN: <token>' https://gitlab.example.com/api/v4/user — 401 means regenerate the token
  2. Regenerate the PAT in GitLab (User Settings > Access Tokens) with api/read_api + read_repository scopes and re-enter it in the connector credential
  3. If OAuth-based, disconnect and redo the OAuth flow to mint a fresh refresh token
  4. Confirm the token owner account is active and not blocked/ deactivated

Example fix

# before: token stored with whitespace / expired
credentials = {"gitlab_access_token": "  glpat-XXXX  \n"}

# after: trim and validate before saving
import re
token = credentials["gitlab_access_token"].strip()
if not re.fullmatch(r"glpat-[A-Za-z0-9_-]{20,}", token):
    raise ValueError("Malformed GitLab PAT — expected glpat-...")
credentials["gitlab_access_token"] = token
Defensive patterns

Strategy: try-catch

Validate before calling

import requests

def gitlab_token_alive(base_url: str, token: str) -> bool:
    r = requests.get(
        f"{base_url.rstrip('/')}/api/v4/user",
        headers={"PRIVATE-TOKEN": token},
        timeout=10,
    )
    return r.status_code == 200

Type guard

def is_valid_gitlab_credential_payload(creds: dict) -> bool:
    tok = creds.get("gitlab_access_token", "")
    return bool(tok) and tok == tok.strip() and tok.startswith("glpat-")

Try / catch

from common.data_source.exceptions import CredentialExpiredError

try:
    connector.validate_connector_settings()
except CredentialExpiredError:
    # prompt user to re-enter token, then retry once
    connector.load_credentials(prompt_for_new_token())
    connector.validate_connector_settings()

Prevention

When it happens

Trigger: Calling validate_connector_settings() (typically from the connector-credential update UI or a test-connection endpoint) when the stored PAT is expired/revoked, was pasted with whitespace or a typo, or belongs to a deleted/deactivated user. Also occurs with OAuth tokens whose refresh failed.

Common situations: Free-tier PAT expiry (90-day for gitlab.com), admin rotating tokens without updating the connector credential, tokens copied from a password manager with trailing newlines, SSO-enforced accounts with personal tokens disabled.

Related errors


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