{"record":{"id":"2a9d56effa237bd4","repo":"n8n-io/n8n","slug":"500","errorCode":"500","errorMessage":"Timeout reached","messagePattern":"Timeout reached","errorType":"exception","errorClass":"NodeApiError","httpStatus":null,"severity":"error","filePath":"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/helpers/polling.ts","lineNumber":18,"sourceCode":"import type { IExecuteFunctions } from 'n8n-workflow';\nimport { NodeApiError } from 'n8n-workflow';\n\nexport async function pollUntilAvailable<TResponse>(\n\tctx: IExecuteFunctions,\n\trequest: () => Promise<TResponse>,\n\tcheck: (response: TResponse) => boolean,\n\ttimeoutSeconds: number,\n\tintervalSeconds = 5,\n): Promise<TResponse> {\n\tconst abortSignal = ctx.getExecutionCancelSignal();\n\tlet response: TResponse | undefined;\n\tconst startTime = Date.now();\n\n\twhile (!response || !check(response)) {\n\t\tconst elapsedTime = Date.now() - startTime;\n\t\tif (elapsedTime >= timeoutSeconds * 1000) {\n\t\t\tthrow new NodeApiError(ctx.getNode(), {\n\t\t\t\tmessage: 'Timeout reached',\n\t\t\t\tcode: 500,\n\t\t\t});\n\t\t}\n\n\t\tif (abortSignal?.aborted) {\n\t\t\tthrow new NodeApiError(ctx.getNode(), {\n\t\t\t\tmessage: 'Execution was cancelled',\n\t\t\t\tcode: 500,\n\t\t\t});\n\t\t}\n\n\t\tresponse = await request();\n\n\t\t// Wait before the next polling attempt\n\t\tawait new Promise((resolve) => setTimeout(resolve, intervalSeconds * 1000));\n\t}\n","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/helpers/polling.ts#L1-L36","documentation":"During async polling (e.g. for batch operations or assistant runs), the pollUntilAvailable helper loops calling request() at intervalSeconds intervals. If the total elapsed time reaches timeoutSeconds before the check() predicate passes, it throws a NodeApiError with code 500. Note: code 500 is semantically misleading — it represents a client-side timeout, not a server error.","triggerScenarios":"A long-running OpenAI async operation (fine-tune, batch, assistant run) that does not reach a terminal state within the configured timeoutSeconds window. The polling loop checks elapsed time before each iteration and aborts.","commonSituations":"Fine-tuning jobs that take longer than expected; assistant runs with heavy tool usage that exceed the timeout; network latency inflating poll response times; timeoutSeconds configured too low for the operation.","solutions":["Increase the timeoutSeconds parameter passed to pollUntilAvailable to accommodate longer-running operations","Check the OpenAI dashboard for the actual job status — it may have completed server-side after the timeout","Reduce the input size or complexity of the async operation so it finishes faster","Verify network connectivity and latency to the OpenAI API"],"exampleFix":"// before — pollUntilAvailable(ctx, request, check, 60, 5)\n// after  — pollUntilAvailable(ctx, request, check, 300, 10)","handlingStrategy":"retry","validationCode":"// Choose timeout based on operation type\nconst timeoutByOperation = {\n  fine_tune: 3600, // 1 hour\n  batch: 7200, // 2 hours\n  assistant_run: 600, // 10 minutes\n};\nconst timeout = timeoutByOperation[operation] ?? 300;\nif (timeout < expectedDuration) {\n  console.warn(`Timeout ${timeout}s may be too short for ${operation}`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await pollUntilAvailable(ctx, request, check, timeoutSeconds, intervalSeconds);\n} catch (error) {\n  if (error instanceof NodeApiError && error.message === 'Timeout reached') {\n    // Check if the job actually completed server-side\n    const status = await checkJobStatus(jobId);\n    if (status === 'completed') return;\n    throw error;\n  }\n  throw error;\n}","preventionTips":["Set timeoutSeconds generously for long operations like fine-tuning","Monitor job status via the OpenAI dashboard independently of the polling loop","Use longer intervalSeconds for very long jobs to reduce API calls","Consider using webhooks instead of polling for job completion if available"],"tags":["openai","timeout","polling","async","long-running"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}