infiniflow/ragflow · warning · Error
Failed to create search
Error message
Failed to create search
What it means
_run_with_timeout runs the OAuth helper in a daemon thread and joins with timeout_secs; if the thread is still alive (flow waiting on user consent in a browser) TimeoutError is raised with the given message. This guards headless/automated runs from hanging forever on the consent screen.
Source
Thrown at web/src/pages/next-searches/hooks.ts:53
interface CreateSearchResponse {
id: string;
name: string;
description: string;
}
export const useCreateSearch = () => {
const { t } = useTranslation();
const {
data,
isError,
mutateAsync: createSearchMutation,
} = useMutation<CreateSearchResponse, Error, CreateSearchProps>({
mutationKey: ['createSearch'],
mutationFn: async (props) => {
const { data: response } = await searchService.createSearch(props);
if (response.code !== 0) {
throw new Error(response.message || 'Failed to create search');
}
return response.data;
},
onSuccess: () => {
message.success(t('message.created'));
},
onError: (error) => {
message.error(t('message.error', { error: error.message }));
},
});
const createSearch = useCallback(
(props: CreateSearchProps) => {
return createSearchMutation(props);
},
[createSearchMutation],
);
View on GitHub (pinned to 554fb1133a)
Solutions
- Re-run the flow from a machine with a working browser and port-forward localhost if remote (ssh -L 8080:localhost:8080)
- Complete the consent screen promptly once the URL appears; close stale tabs from earlier attempts first
- For fully headless setups, avoid the interactive flow entirely — use a service-account credential or paste a pre-minted token blob
Example fix
# before: headless box, nobody clicks consent creds = _run_with_timeout(flow.run_local_server, timeout_secs=300, ...) # TimeoutError # after: run on a browser-capable host, or forward the callback port # local:$ ssh -L 8080:localhost:8080 ci-host # ci-host:$ python scripts/google_oauth_flow.py # then click through locally
Defensive patterns
Strategy: try-catch
Validate before calling
import os, socket
def oauth_flow_env_ok() -> bool:
# rough check: can we bind the callback port, is there a display/browser?
try:
s = socket.socket(); s.bind(("localhost", 0)); s.close()
return os.environ.get("DISPLAY") is not None or os.environ.get("SSH_TUNNEL") == "1"
except OSError:
return False Try / catch
try:
token = run_oauth_with_timeout(flow, timeout_secs=300)
except TimeoutError:
# no one completed consent — fall back to pre-minted token, don't loop
token = json.loads(get_stored_token_blob())
if not token:
print("Run the flow from a machine with a browser (ssh -L 8080:localhost:8080).") Prevention
- Run interactive OAuth only from a desktop session; use ssh -L for remote hosts
- Raise timeout_secs generously for first-time consents
- Keep a pre-minted token blob as the fallback for headless re-runs
When it happens
Trigger: Running the interactive local-server OAuth flow (or console fallback) where nobody completes the Google consent page within the timeout — typical in CI, containers, or SSH sessions without browser forwarding.
Common situations: Developer runs the token-generation script inside docker/CI, browser opens on the wrong machine, user steps away mid-consent, proxy blocking localhost:8080 callback.
Related errors
- Failed to fetch search detail
- main() must be defined or exported.
- Invalid chat_id: ${payload.chat_id}
- main() must be defined or exported.
- main() returned a non-JSON-serializable value.
AI-assisted analysis of infiniflow/ragflow@554fb1133a (2026-08-15).
Data as JSON: /api/errors/81886f87a584d8e0.
Report an issue: GitHub.