danny-avila/LibreChat · error · Error

[waitForRun] ${runIdLog} | Run retrieval failed after ${maxR

Error message

[waitForRun] ${runIdLog} | Run retrieval failed after ${maxRetries} attempts

What it means

Thrown by waitForRun in Runs/handle.js after the inner retry loop exhausts maxRetries (5) attempts at retrieving the run from the OpenAI Assistants API without ever obtaining an updatedRun. Each attempt wraps retrieveRun in a 3-second withTimeout; all five attempts either threw or timed out, so the run status is unknowable and polling cannot continue safely.

Source

Thrown at api/server/services/Runs/handle.js:111

          raceTimeoutMs,
          `[heartbeat ${i}] ${runIdLog} | Run retrieval timed out after ${raceTimeoutMs} ms. Trying again (attempt ${
            attempt + 1
          } of ${maxRetries})...`,
        );
        const endTime = Date.now();
        logger.debug(
          `[heartbeat ${i}] ${runIdLog} | Elapsed run retrieval time: ${endTime - startTime}`,
        );
      } catch (error) {
        attempt++;
        startTime = Date.now();
        logger.warn(`${runIdLog} | Error retrieving run status`, error);
      }
    }

    if (!updatedRun) {
      const errorMessage = `[waitForRun] ${runIdLog} | Run retrieval failed after ${maxRetries} attempts`;
      throw new Error(errorMessage);
    }

    run = updatedRun;
    attempt = 0;
    const runStatus = `${runInfo} | status: ${run.status}`;

    if (run.status !== lastSeenStatus) {
      logger.debug(`[${run.status}] ${runInfo}`);
      lastSeenStatus = run.status;
    }

    logger.debug(`[heartbeat ${i}] ${runStatus}`);

    let cancelStatus;
    try {
      const timeoutMessage = `[heartbeat ${i}] ${runIdLog} | Cancel Status check operation timed out.`;
      cancelStatus = await withTimeout(cache.get(cacheKey), raceTimeoutMs, timeoutMessage);
    } catch (error) {

View on GitHub (pinned to 5ff282f900)

Solutions

  1. Check the OpenAI API status page and the application's network egress (DNS, proxy, firewall).
  2. Verify openai.apiKey is valid and the organization is in good standing (test with a direct curl to /v1/threads).
  3. Increase maxRetries and/or raceTimeoutMs if the failures are transient and you can afford longer polling.
  4. Inspect the warn-level logs ('Error retrieving run status') emitted per attempt — they carry the underlying error that all five attempts shared.

Example fix

// before
async function waitForRun({ openai, run_id, thread_id, runManager }) { /* default maxRetries=5, raceTimeoutMs=3000 */ }

// after (caller)
try {
  await waitForRun({ openai, run_id, thread_id, runManager });
} catch (err) {
  if (err.message.includes('Run retrieval failed after')) {
    // surface to user, do not auto-retry blindly
    return { error: 'Assistant run is unreachable right now. Please try again.' };
  }
  throw err;
}
Defensive patterns

Strategy: retry

Validate before calling

if (!openai?.apiKey || !thread_id || !run_id) {
  throw new Error('Cannot wait for run: missing apiKey, thread_id, or run_id');
}

Try / catch

try {
  await waitForRun({ openai, run_id, thread_id, runManager });
} catch (err) {
  if (err.message.includes('Run retrieval failed after')) {
    // notify user; do not blind-retry the same run indefinitely
    return { error: 'Assistant run is unreachable. Please retry.' };
  }
  throw err;
}

Prevention

When it happens

Trigger: OpenAI API outage or sustained 5xx; network partition blocking egress to the API base URL; invalid/expired apiKey producing consistent 401s; wrong baseURL pointing at a non-Assistants endpoint; thread_id/run_id that does not exist on the upstream; a proxy under heavy load timing out every request within 3s.

Common situations: Rate limiting (429) sustained across all retries; a self-hosted/proxy baseURL misconfigured; an OpenAI organization suspension; transient DNS failures in the deployment.

Related errors


AI-assisted analysis of danny-avila/LibreChat@5ff282f900 (2026-08-12). Data as JSON: /api/errors/969064eda3d60501. Report an issue: GitHub.