infiniflow/ragflow · error · Error

main() must return a value. Use null for an empty result.

Error message

main() must return a value. Use null for an empty result.

What it means

Raised when python-gitlab returns GitlabAuthorizationError (HTTP 403): the token authenticates fine but the authenticated user is not permitted to perform the action. In this validator it usually means the token cannot see the project owner/name being fetched. Maps to InsufficientPermissionsError.

Source

Thrown at agent/sandbox/result_protocol.py:50

    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 "", {}

    cleaned_lines: list[str] = []
    structured_result: dict[str, Any] = {}

    for line in str(stdout).splitlines():

View on GitHub (pinned to 554fb1133a)

Solutions

  1. Give the token's user at least Reporter role on the target project (or group)
  2. Recreate the PAT with the api scope (or at minimum read_api + read_repository)
  3. Check GitLab group Settings > Network > IP restrictions and allow the connector host
  4. Verify the project path owner/name is the intended one — a wrong path on a private namespace also surfaces as 403

Example fix

# before: token only has read_user scope → auth ok, project get 403
gl = gitlab.Gitlab(url, private_token=token)  # token scopes: read_user

# after: mint token with proper scopes and grant project access
gl = gitlab.Gitlab(url, private_token=token)  # token scopes: api, read_repository
# then in GitLab: Project > Members > add token user as Reporter
Defensive patterns

Strategy: try-catch

Validate before calling

import requests

def can_read_project(base_url: str, token: str, owner: str, name: str) -> bool:
    r = requests.get(
        f"{base_url.rstrip('/')}/api/v4/projects/{quote(owner, safe='/')}%2F{name}",
        headers={"PRIVATE-TOKEN": token},
        timeout=10,
    )
    return r.status_code == 200

Type guard

def token_has_needed_scopes(base_url: str, token: str) -> bool:
    r = requests.get(f"{base_url.rstrip('/')}/api/v4/personal_access_tokens/self",
                     headers={"PRIVATE-TOKEN": token}, timeout=10)
    if r.status_code != 200:
        return False
    scopes = set(r.json().get("scopes", []))
    return "api" in scopes or {"read_api", "read_repository"} <= scopes

Try / catch

from common.data_source.exceptions import InsufficientPermissionsError

try:
    connector.validate_connector_settings()
except InsufficientPermissionsError:
    surface_to_admin(
        f"Grant token user at least Reporter on {connector.project_owner}/{connector.project_name} "
        f"and give the token the 'api' scope."
    )

Prevention

When it happens

Trigger: gitlab_client.auth() succeeds but projects.get(f"{owner}/{name}") returns 403 because the token's user has no Guest+ role on that (private) project, the token lacks the api scope (e.g. read_user only), or an IP-restriction/protected-branch policy blocks API access to the project.

Common situations: Using a read-only or narrowly-scoped PAT instead of one with api scope, project under a group the service account was never invited to, group-level IP allowlist that excludes the indexer's egress IP.

Related errors


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