Skip to content

[IncidentIQ] Fix: ArrayIndexOutOfBoundsException - #4

Open
saranyakannan wants to merge 1 commit into
mainfrom
fix/incidentiq-ArrayIndexOutOfBoundsException
Open

[IncidentIQ] Fix: ArrayIndexOutOfBoundsException#4
saranyakannan wants to merge 1 commit into
mainfrom
fix/incidentiq-ArrayIndexOutOfBoundsException

Conversation

@saranyakannan

Copy link
Copy Markdown
Owner

🤖 Auto-Fix by IncidentIQ

Error

ArrayIndexOutOfBoundsException

Root Cause

StackOverflowError - Infinite recursion detected in CategoryService.getSubCategories(). Circular reference in category tree. The ErrorController's /error/stackoverflow endpoint calls an infiniteRecursion helper method without a proper termination condition, leading to a StackOverflowError. The log message within the ErrorController simulates a CategoryService issue.

Fix Applied

Added a recursion guard (depth limit) to the infiniteRecursion method in ErrorController.java to prevent StackOverflowError by terminating the recursion after a defined depth.

Full Incident Report

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🚨 SRE INCIDENT REPORT
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

📋 INCIDENT SUMMARY
Service: user-api
Severity: HIGH
Errors: 1
Warnings: 0
Status: ACTIVE 🚨

🔍 ERRORS DETECTED FROM CLOUD LOGGING

  • StackOverflowError

📊 LOG EVIDENCE

{
  "insertId": "1v5rzk3f5s78up",
  "jsonPayload": {
    "errorType": "StackOverflowError",
    "message": "HTTP 500: StackOverflowError - Infinite recursion detected in CategoryService.getSubCategories(). Circular reference in category tree.",
    "stackTrace": "java.lang.StackOverflowError\nat sre.errorservice.ErrorController.infiniteRecursion(ErrorController.java:424)\nat sre.errorservice.ErrorController.infiniteRecursion(ErrorController.java:424)\nat sre.errorservice.ErrorController.infiniteRecursion(ErrorController.java:424)\n... (repeats many times) ...\nat sre.errorservice.ErrorController.infiniteRecursion(ErrorController.java:424)\n",
    "severity": "ERROR",
    "environment": "production",
    "httpStatusCode": 500,
    "endpoint": "/api/error/stackoverflow",
    "serviceName": "user-api"
  },
  "resource": {
    "type": "cloud_run_revision",
    "labels": {
      "project_id": "sre-platform-491809",
      "revision_name": "user-api-v1",
      "location": "us-central1",
      "service_name": "user-api",
      "configuration_name": ""
    }
  },
  "timestamp": "2026-04-08T18:06:33.003784322Z",
  "severity": "ERROR",
  "logName": "projects/sre-platform-491809/logs/sre-error-service",
  "receiveTimestamp": "2026-04-08T18:06:33.003784322Z"
}

🔧 RECOMMENDED FIXES
The infinite recursion needs to be identified and resolved in the CategoryService.getSubCategories() method or any methods it calls that interact with the category tree. This typically involves:

  1. Adding a Base Case to Recursion: Ensure all recursive calls have a condition that eventually terminates the recursion.
  2. Detecting/Breaking Circular References: When traversing hierarchical data structures like a category tree, implement mechanisms to detect and handle circular references (e.g., using a Set to keep track of visited nodes to prevent re-processing).
  3. Converting to Iterative Approach: For very deep or potentially circular hierarchies, an iterative approach (e.g., using a Queue or Stack) can often be more robust than recursion, as it avoids stack limitations.

Example Code Snippet (Conceptual - with circular reference detection using a visited set):

// In CategoryService.java
public List<Category> getSubCategories(Category category) {
    return getSubCategories(category, new HashSet<>());
}

private List<Category> getSubCategories(Category category, Set<String> visitedCategoryIds) {
    List<Category> allSubCategories = new ArrayList<>();
    if (category == null || category.getSubCategories() == null || visitedCategoryIds.contains(category.getId())) {
        // Base case: null category, no sub-categories, or already visited (circular reference detected)
        return allSubCategories; 
    }

    visitedCategoryIds.add(category.getId()); // Mark current category as visited

    for (Category sub : category.getSubCategories()) {
        allSubCategories.add(sub);
        // Recursively get sub-categories, passing the visited set
        allSubCategories.addAll(getSubCategories(sub, visitedCategoryIds)); 
    }
    return allSubCategories;
}

⚡ IMMEDIATE ACTIONS (Do These NOW)

  1. Rollback to Last Stable Version: Roll back the user-api service to its last known stable revision.
    Example:
    gcloud run services update user-api \
      --to-revision user-api-v0 \
      --region us-central1
    (Note: Replace user-api-v0 with the actual name of your last stable revision.)
  2. Temporarily Disable Endpoint (if rollback not immediate):: Consider temporarily disabling or rate-limiting access to the /api/error/stackoverflow endpoint.
  3. Deploy Fixed Image (if available): If a new, fixed image is available, deploy it.
    Example:
    gcloud run services update user-api \
      --image gcr.io/sre-platform-491809/user-api:fixed-version \
      --region us-central1

🛡️ PREVENTION

  1. Thorough Code Reviews: Implement stringent code reviews for any new or modified recursive functions, particularly those dealing with hierarchical data structures, to ensure proper termination conditions and handling of potential cycles.
  2. Unit and Integration Testing: Develop comprehensive unit tests for CategoryService.getSubCategories() and other recursive methods. Specifically, create integration tests that simulate category trees with circular references to ensure the code handles them gracefully (e.g., by throwing a specific exception or returning an empty list for the circular path) rather than overflowing the stack.
  3. Data Validation: Implement validation logic at the data layer to prevent the creation of circular references in the Category data itself. For example, when updating category relationships, check for cycles before persisting changes.
  4. Static Code Analysis Tools: Utilize static analysis tools (e.g., SonarQube, FindBugs) in your CI/CD pipeline to identify potential infinite recursion patterns or other common coding pitfalls.
  5. Monitoring Stack Depth: While harder to directly monitor in production, logging the depth of recursive calls in non-error situations can provide insights into potentially problematic deep recursion before it becomes an Error.
  6. Increase JVM Stack Size (as a last resort/temporary measure): While not a fix for infinite recursion, if legitimate, very deep recursion is expected (not the case here), the JVM stack size could be increased.
    JAVA_TOOL_OPTIONS="-Xss4m" # Sets stack size to 4MB (default is often 1MB or 2MB)
    
    This would be set for the Cloud Run service via the --set-env-vars flag:
    gcloud run services update user-api --set-env-vars "JAVA_TOOL_OPTIONS=-Xss4m" --region us-central1
    However, for infinite recursion, this will only delay the inevitable and is not a recommended solution.

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Generated by IncidentIQ SRE Agent

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant