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

Constructor validation in GoogleDriveConnector.__init__: every indexing mode flag is falsy. The connector refuses to run a sync that would index nothing. Raised as ConnectorValidationError at construction time, before any credentials are touched.

Source

Thrown at internal/agent/sandbox/result_protocol.go:113

	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.
//
// The Python side returns `(cleaned_stdout, structured_result_dict)`.
// On Go the dict is `map[string]any`.
//
// Edge cases (matching the Python implementation):

View on GitHub (pinned to 554fb1133a)

Solutions

  1. Enable at least one source: set include_my_drives=True for the admin's own drive, or list shared_drive_urls/shared_folder_urls/my_drive_emails
  2. If you intended everything, include_shared_drives=True plus include_my_drives=True is the broadest combination
  3. If the flags come from user input, validate them in the form before constructing the connector

Example fix

# before
connector = GoogleDriveConnector(
    include_shared_drives=False,
    include_my_drives=False,
    include_files_shared_with_me=False,
    shared_folder_urls=[],
    my_drive_emails=[],
)

# after
connector = GoogleDriveConnector(
    include_shared_drives=True,
    include_my_drives=True,
    include_files_shared_with_me=False,
    shared_folder_urls=[],
    my_drive_emails=[],
)
Defensive patterns

Strategy: validation

Validate before calling

def has_index_target(cfg: dict) -> bool:
    return any((
        cfg.get("include_shared_drives"),
        cfg.get("include_my_drives"),
        cfg.get("include_files_shared_with_me"),
        cfg.get("shared_folder_urls"),
        cfg.get("my_drive_emails"),
        cfg.get("shared_drive_urls"),
    ))

if not has_index_target(config):
    raise ValueError("Select at least one Drive source to index")

Prevention

When it happens

Trigger: Instantiating GoogleDriveConnector (or saving the connector-pair config) with include_shared_drives=False, include_my_drives=False, include_files_shared_with_me=False, and empty shared_folder_urls / my_drive_emails / shared_drive_urls.

Common situations: UI form where all checkboxes were left unchecked, JSON config template with all flags defaulted false, a config-generation script that only emits keys when truthy.

Related errors


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