{"record":{"id":"5cc28924606eb1bd","repo":"FlowiseAI/Flowise","slug":"arxiv-api-error-response-status-response-sta","errorCode":null,"errorMessage":"Arxiv API error: ${response.status} ${response.statusText}","messagePattern":"Arxiv API error: (.+?) (.+?)","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/components/nodes/tools/Arxiv/core.ts","lineNumber":159,"sourceCode":"            })\n        } else {\n            // Search by query\n            // Remove problematic characters that can cause search issues\n            const cleanedQuery = query.replace(/[:-]/g, '').substring(0, this.maxQueryLength)\n            searchParams = new URLSearchParams({\n                search_query: `all:${cleanedQuery}`,\n                max_results: this.topKResults.toString(),\n                sortBy: 'relevance',\n                sortOrder: 'descending'\n            })\n        }\n\n        const url = `${baseUrl}?${searchParams.toString()}`\n        this.logger?.info(`[${this.orgId}]: Making Arxiv API call to: ${url}`)\n\n        const response = await fetch(url)\n        if (!response.ok) {\n            throw new Error(`Arxiv API error: ${response.status} ${response.statusText}`)\n        }\n\n        const xmlText = await response.text()\n        return this.parseArxivResponse(xmlText)\n    }\n\n    private async downloadAndExtractPdf(arxivId: string): Promise<string> {\n        // Extract clean arxiv ID from full URL if needed\n        const cleanId = arxivId.replace('http://arxiv.org/abs/', '').replace('https://arxiv.org/abs/', '')\n        const pdfUrl = `https://arxiv.org/pdf/${cleanId}.pdf`\n\n        this.logger?.info(`[${this.orgId}]: Downloading PDF from: ${pdfUrl}`)\n\n        const response = await fetch(pdfUrl)\n        if (!response.ok) {\n            throw new Error(`Failed to download PDF: ${response.status} ${response.statusText}`)\n        }\n","sourceCodeStart":141,"sourceCodeEnd":177,"githubUrl":"https://github.com/FlowiseAI/Flowise/blob/abe4a8601a058047b350c260676826e21dd14101/packages/components/nodes/tools/Arxiv/core.ts#L141-L177","documentation":"Thrown by ArxivTool.fetchResults when the HTTP response to the Arxiv search endpoint is not ok (non-2xx). The status code and status text are interpolated. Arxiv's export API (http://export.arxiv.org/api/query) is rate-limited and occasionally returns 429 or 5xx, so a non-ok response is treated as a hard failure rather than returning empty results.","triggerScenarios":"HTTP 429 Too Many Requests from Arxiv's per-IP rate limit; 5xx during Arxiv outages; 403 from a proxy/firewall blocking the export endpoint; DNS/TLS errors surfaced as a non-ok response by the runtime.","commonSituations":"Burst workloads (many agents querying Arxiv in parallel); running from a cloud egress IP that Arxiv throttles aggressively; corporate proxy rewriting the request.","solutions":["Retry with exponential backoff specifically on 429 and 5xx — Arxiv rate limits are transient.","Reduce parallelism: serialize Arxiv calls and cap topKResults to what you actually need.","Set a sensible User-Agent if the runtime allows it; some Arxiv edge nodes reject default fetch UA strings.","If the error persists, check https://status.arxiv.org for an ongoing outage."],"exampleFix":"// before\nconst response = await fetch(url)\nif (!response.ok) {\n  throw new Error(`Arxiv API error: ${response.status} ${response.statusText}`)\n}\n// after: retry on transient codes\nasync function fetchWithRetry(url: string, attempts = 3) {\n  for (let i = 0; i < attempts; i++) {\n    const r = await fetch(url)\n    if (r.ok || (r.status !== 429 && r.status < 500)) return r\n    await new Promise((res) => setTimeout(res, 2 ** i * 500))\n  }\n  throw new Error(`Arxiv API error after retries: ${url}`)\n}","handlingStrategy":"retry","validationCode":"async function arxivOk(url: string): Promise<boolean> {\n  const r = await fetch(url, { method: 'GET' })\n  return r.ok\n}","typeGuard":null,"tryCatchPattern":"async function fetchArxiv(url: string, attempts = 3) {\n  for (let i = 0; i < attempts; i++) {\n    const r = await fetch(url)\n    if (r.ok) return r\n    if (r.status !== 429 && r.status < 500) {\n      throw new Error(`Arxiv API error: ${r.status} ${r.statusText}`)\n    }\n    await new Promise((res) => setTimeout(res, 2 ** i * 500))\n  }\n  throw new Error('Arxiv API error: giving up after retries')\n}","preventionTips":["Serialize Arxiv calls and cap concurrency to stay under the rate limit.","Cache query results to avoid repeat traffic.","Monitor Arxiv status page during bulk ingestion."],"tags":["network","arxiv","http","api","rate-limit"],"backgroundTag":null,"analyzedSha":"abe4a8601a058047b350c260676826e21dd14101","analyzedAt":"2026-08-12T16:04:40.823Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}