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
- Give the token's user at least Reporter role on the target project (or group)
- Recreate the PAT with the api scope (or at minimum read_api + read_repository)
- Check GitLab group Settings > Network > IP restrictions and allow the connector host
- 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
- Document required role (Reporter+) and scopes (api) next to the credential form
- Use a dedicated bot/service account with explicit project membership instead of a personal token
- For self-hosted GitLab behind IP allowlists, pin the indexer's egress IP
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
- Insufficient permissions to access Bitbucket workspace (HTTP
- Jira token does not have permission to access the requested
- main() must be defined or exported.
- main() returned a non-JSON-serializable value.
- WhatsApp session is not running.
AI-assisted analysis of infiniflow/ragflow@554fb1133a (2026-08-15).
Data as JSON: /api/errors/2037b5f132d07f44.
Report an issue: GitHub.