danny-avila/LibreChat · error · Error

Unexpected run status ${run.status}.\nFull run info:\n\n${ru

Error message

Unexpected run status ${run.status}.\nFull run info:\n\n${runInfo}

What it means

Thrown when an Assistants API run object has a status the code does not recognize as a terminal or actionable state (e.g. not completed, requires_action, failed, cancelled, expired, in_progress). The full run JSON is appended so the unhandled status can be diagnosed.

Source

Thrown at api/server/services/AssistantService.js:108

  } else if (run.status === RunStatus.REQUIRES_ACTION) {
    const actions = [];
    run.required_action?.submit_tool_outputs.tool_calls.forEach((item) => {
      const functionCall = item.function;
      const args = JSON.parse(functionCall.arguments);
      actions.push({
        tool: functionCall.name,
        toolInput: args,
        toolCallId: item.id,
        run_id,
        thread_id,
      });
    });

    return actions;
  }

  const runInfo = JSON.stringify(run, null, 2);
  throw new Error(`Unexpected run status ${run.status}.\nFull run info:\n\n${runInfo}`);
}

/**
 * Filters the steps to keep only the most recent instance of each unique step.
 * @param {RunStep[]} steps - The array of RunSteps to filter.
 * @return {RunStep[]} The filtered array of RunSteps.
 */
function filterSteps(steps = []) {
  if (steps.length <= 1) {
    return steps;
  }
  const stepMap = new Map();

  steps.forEach((step) => {
    if (!step) {
      return;
    }

View on GitHub (pinned to 5ff282f900)

Solutions

  1. Upgrade to a version of the code that handles the new status returned in runInfo.
  2. If the status is transient, retry the run fetch/poll after a short delay.
  3. Inspect runInfo in the logs to identify the exact unhandled status and add a handler.
  4. Pin the Assistants API version to one whose status set is fully handled.
Defensive patterns

Strategy: validation

Validate before calling

const KNOWN_STATUSES = new Set(['queued','in_progress','requires_action','completed','failed','cancelled','expired','cancelling']);
if (!KNOWN_STATUSES.has(run.status)) {
  throw new Error(`Unhandled run status: ${run.status}`);
}

Type guard

function isKnownRunStatus(status) {
  return ['queued','in_progress','requires_action','completed','failed','cancelled','expired','cancelling'].includes(status);
}

Try / catch

try { await processRun(run); }
catch (e) {
  if (/Unexpected run status/.test(e.message)) { logger.warn(e.message); await sleep(1000); return pollRun(run.id); }
  throw e;
}

Prevention

When it happens

Trigger: OpenAI introduced a new run status value not yet handled by this version of the code; a polling/processing path received a status like 'cancelling' or a future status mid-flight.

Common situations: API version drift — the provider adds a status after this code shipped; a race where a run transitions to an intermediate state the loop did not expect.

Related errors


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