infiniflow/ragflow · error · Error
Failed to delete search
Error message
Failed to delete search
What it means
Thrown by the useDeleteSearch React Query mutation in web/src/pages/next-searches/hooks.ts:272 when the backend DELETE-search API responds with a non-zero business code. The service layer (searchService.deleteSearch) resolves the HTTP call successfully, but RAGFlow's API convention returns code !== 0 to signal a server-side rejection (missing search, permission denied, DB error). The hook converts that into a generic Error whose message falls back to 'Failed to delete search' when the server message is empty.
Source
Thrown at web/src/pages/next-searches/hooks.ts:272
},
});
return { data: data?.data, isLoading, isError };
};
export const useDeleteSearch = () => {
const { t } = useTranslation();
const queryClient = useQueryClient();
const {
data,
isError,
mutateAsync: deleteSearchMutation,
} = useMutation<DeleteSearchResponse, Error, DeleteSearchProps>({
mutationKey: ['deleteSearch'],
mutationFn: async (props) => {
const { data: response } = await searchService.deleteSearch(props);
if (response.code !== 0) {
throw new Error(response.message || 'Failed to delete search');
}
queryClient.invalidateQueries({ queryKey: ['searchList'] });
return response;
},
onSuccess: () => {
message.success(t('message.deleted'));
},
onError: (error) => {
message.error(t('message.error', { error: error.message }));
},
});
const deleteSearch = useCallback(
(props: DeleteSearchProps) => {
return deleteSearchMutation(props);
},
[deleteSearchMutation],View on GitHub (pinned to 554fb1133a)
Solutions
- Log the full response (code + message) from searchService.deleteSearch before throwing to surface the real backend reason
- Verify the search_id still exists in the ['searchList'] cache before invoking the mutation
- Confirm authentication is valid (token/cookie) by re-issuing the request after login refresh
- Check backend logs for the corresponding DELETE search request to see the server-side error
- If the search was already deleted (404-style code), treat it as success and invalidate ['searchList'] anyway
Example fix
// before
if (response.code !== 0) {
throw new Error(response.message || 'Failed to delete search');
}
// after
if (response.code !== 0) {
const alreadyGone = /not exist|not found/i.test(response.message || '');
if (alreadyGone) {
queryClient.invalidateQueries({ queryKey: ['searchList'] });
return response;
}
throw new Error(response.message || 'Failed to delete search');
} Defensive patterns
Strategy: try-catch
Validate before calling
const existsInCache = (queryClient, searchId) =>
queryClient
.getQueryData(['searchList'])
?.pages?.flat?.()?.some?.((s) => s.id === searchId) ?? true; Type guard
const isApiEnvelope = (v: any): v is { code: number; message?: string; data?: unknown } =>
typeof v === 'object' && v !== null && typeof v.code === 'number'; Try / catch
try {
await deleteSearchMutation({ search_id: id });
} catch (e) {
if (/not (exist|found)/i.test(e.message)) {
queryClient.invalidateQueries({ queryKey: ['searchList'] });
return;
}
message.error(e.message);
} Prevention
- Invalidate ['searchList'] on mount so stale ids are pruned before delete attempts
- Centralize code!==0 handling in a response interceptor so message is never lost
When it happens
Trigger: Calling the deleteSearch mutation with a search_id that no longer exists; the API session/token expired so the backend returns an error code; a proxy or gateway returns a 200-wrapped error payload with code != 0; the response body lacks a message field so the fallback string is used.
Common situations: Stale UI list: user deletes a search that another tab/session already removed. Logged-out token after session timeout. Backend API version change where the delete endpoint moved or was renamed. Multi-tenant permission mismatch (search owned by another user).
Related errors
- Failed to update search
- Failed to list skills folder
- Failed to delete skill
- dataset_id (or kb_id/knowledge_id) is required for retrieval
- SerpApi returned no organic_results.
AI-assisted analysis of infiniflow/ragflow@554fb1133a (2026-08-15).
Data as JSON: /api/errors/a6ac9635b5f2310e.
Report an issue: GitHub.