Skip to content

Infinite recursion in checkShouldRespond on API failure #46

Description

@cubrift

Issue

The checkShouldRespond() function in messages/ai/CheckShouldRespond.js (line 24) has infinite recursion potential without proper stack limit protection.

Current code (lines 21-25):

catch (error) {
  logger.error(error, 'Error occurred while checking if response is needed');
  if (abortController.signal.aborted) return false;
  return checkShouldRespond(model, messages, abortController);  // Recursive call
}

Problem

If the API call consistently fails (network error, quota exceeded, API down), the function will recursively call itself indefinitely, eventually causing a stack overflow crash.

Impact

  • Denial of Service: Message processing hangs with recursive calls, consuming memory
  • Application Crash: Stack overflow after enough consecutive API failures
  • No Recovery Path: No maximum recursion depth or exponential backoff

Suggested Fix

Add a retry counter and exponential backoff:

async function checkShouldRespond(model, messages, abortController, retryCount = 0) {
  if (!messages) return false;
  if (!messages.find(f => typeof f.content === 'string')) return false;
  try {
    const { _output } = await generateText({
      model: model(CHECK_MODEL),
      output: Output.object({ schema }),
      system: checkInstructions,
      abortSignal: abortController.signal,
      messages: messages.slice(-10)
    });
    logger.debug(_output, 'Check should respond output');
    if (abortController.signal.aborted) return false;
    return _output.shouldRespond;
  } catch (error) {
    logger.error(error, 'Error occurred while checking if response is needed');
    if (abortController.signal.aborted) return false;
    
    const maxRetries = 3;
    if (retryCount >= maxRetries) {
      logger.warn('Max retries exceeded for checkShouldRespond, defaulting to false');
      return false;  // Safe default
    }
    
    // Exponential backoff
    await new Promise(resolve => setTimeout(resolve, Math.pow(2, retryCount) * 100));
    return checkShouldRespond(model, messages, abortController, retryCount + 1);
  }
}

Affected File

  • messages/ai/CheckShouldRespond.js:21-25

Type

Bug - potential stack overflow from infinite recursion

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingcodexUse for codex-generated issues only.good first issueGood for newcomers

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions