infiniflow/ragflow · critical · Error
main() must be defined or exported.
Error message
main() must be defined or exported.
What it means
Same guard as error 624, but on the permission-sync path retrieve_all_slim_docs_perm_sync: the connector was asked to enumerate document IDs for ACL sync before any GitLab client exists because load_credentials() never ran.
Source
Thrown at internal/agent/sandbox/result_protocol.go:109
// syntax-significant characters) and decoded at runtime via
// JSON.parse(Buffer.from(..., 'base64').toString('utf8')), so the
// only Go-side dataflow into the JS source is the base64 string.
func BuildJavaScriptWrapper(code, argsJSON string) string {
argsB64 := base64.StdEncoding.EncodeToString([]byte(argsJSON))
// Note: this string is *embedded inside* a Go raw string, but the
// Go raw string and the JS source are independent languages. We
// need the final JS to be valid; the doubled braces {{ }} are JS
// template-literal escapes only on the JS side. We pass them
// through as-is.
return code + `
const __ragflowArgsB64 = "` + argsB64 + `";
const __ragflowArgs = JSON.parse(Buffer.from(__ragflowArgsB64, 'base64').toString('utf8'));
(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('` + resultMarkerPrefix + `' + Buffer.from(payload, 'utf8').toString('base64'));
})();
`
}
// ExtractStructuredResult scans stdout for the marker line, decodes
// the JSON payload after it, and returns the user-visible stdout
// (with the marker line removed) plus the parsed structured result.
//View on GitHub (pinned to 554fb1133a)
Solutions
- Confirm the connector credential exists and load_credentials() succeeded before scheduling perm sync
- Re-create or re-enter the GitLab credential if it was deleted
- Gate perm-sync scheduling on a successful validate_connector_settings() run
Example fix
# before slim = connector.retrieve_all_slim_docs_perm_sync() # no creds loaded # after connector.load_credentials(creds) connector.validate_connector_settings() slim = connector.retrieve_all_slim_docs_perm_sync()
Defensive patterns
Strategy: validation
Validate before calling
def perm_sync_ready(connector) -> bool:
return connector.gitlab_client is not None and connector.credentials_loaded Try / catch
from common.data_source.exceptions import ConnectorMissingCredentialError
try:
slim = connector.retrieve_all_slim_docs_perm_sync(cb)
except ConnectorMissingCredentialError:
reattach_credentials(connector) # reload from credential store, reschedule
slim = connector.retrieve_all_slim_docs_perm_sync(cb) Prevention
- Schedule perm-sync only after a successful validate_connector_settings()
- Persist credential IDs with connectors so background jobs can reload them
- Alert when a credential referenced by a scheduled job is deleted
When it happens
Trigger: Invoking retrieve_all_slim_docs_perm_sync(callback) on a freshly constructed connector, or a perm-sync job scheduled against a connector whose credential payload failed to parse so the client was never set.
Common situations: Background perm-sync job racing ahead of credential provisioning, deleted/expired credential entry removed while the perm-sync task still references the connector.
Related errors
- Invalid chat_id: ${payload.chat_id}
- main() must be defined or exported.
- Failed to read compilation status
- Jira
- main() must return a value. Use null for an empty result.
AI-assisted analysis of infiniflow/ragflow@554fb1133a (2026-08-15).
Data as JSON: /api/errors/bd18f1443fe1e0a9.
Report an issue: GitHub.