OpenHands / OpenHands/enterprise

[Feature/Bug]: Cloud API should return rate limit error (429) instead of silently pausing existing runtimes

Open
#21 9 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
4
Forks
2
Avg merge
1d 22h
Merged PRs (30d)
101

Description

Summary

When a user hits the maximum number of concurrent runtimes via the Cloud API, the current behavior automatically pauses older sandboxes to make room for new ones. This happens silently from the API caller's perspective - they successfully start a new conversation while their existing conversations are paused without notification.

This behavior may be surprising and problematic for API users who expect either:

  1. A rate limit error (HTTP 429) when they exceed their limit, OR
  2. An explicit notification that older runtimes will be paused

Current Behavior

From openhands/app_server/sandbox/remote_sandbox_service.py:

async def start_sandbox(
    self, sandbox_spec_id: str | None = None, sandbox_id: str | None = None
) -> SandboxInfo:
    """Start a new sandbox by creating a remote runtime."""
    try:
        # Enforce sandbox limits by cleaning up old sandboxes
        await self.pause_old_sandboxes(self.max_num_sandboxes - 1)  # <-- This pauses older sandboxes
        
        # ... then starts the new sandbox

The pause_old_sandboxes method (lines 586-633):

  • Identifies sandboxes that exceed the limit
  • Pauses (not kills) the oldest sandboxes
  • Does not return any error to the caller

Documentation vs Implementation

The Cloud API documentation states:

"If you have too many conversations running at once, older conversations will be paused to limit the number of concurrent conversations."

While this matches the implementation, API users may not expect this behavior without explicit notification.

Related Context

  • PR OpenHands/OpenHands#359 in runtime-api (merged Nov 2025) updated the runtime-api to return HTTP 429 instead of HTTP 400 when the runtime limit is exceeded
  • However, this only applies when the runtime-api itself enforces the limit, not when the app server proactively pauses sandboxes

Potential Solutions

Option 1: Return 429 before pausing (Strict rate limiting)

Return HTTP 429 (Too Many Requests) when the user has reached their maximum number of runtimes, instead of automatically pausing older ones.

Pros:

  • Standard HTTP semantics for rate limiting
  • Clear feedback to API users
  • Users can decide whether to explicitly stop an existing conversation

Cons:

  • Breaking change from current behavior
  • May require API users to handle rate limits explicitly
Option 2: Include paused conversations in response (Informative approach)

When starting a new conversation that causes older ones to be paused, include this information in the response:

{
  "id": "new-conversation-id",
  "status": "WORKING",
  "paused_conversations": ["old-conv-1", "old-conv-2"],
  "message": "2 existing conversations were paused to start this conversation"
}

Pros:

  • Backwards compatible
  • Informs users what happened
  • Users can choose to resume paused conversations if needed

Cons:

  • Non-standard response format
  • May require API client updates
Option 3: Add opt-out flag (User choice)

Add a parameter like auto_pause_existing: bool = True that users can set to false if they prefer to receive a 429 error instead of having older conversations paused.

Pros:

  • Preserves current default behavior
  • Gives users control
  • Backwards compatible

Cons:

  • Additional API complexity

Environment

  • OpenHands Cloud (app.all-hands.dev)
  • Affects /api/v1/app-conversations endpoint
  • Code location: openhands/app_server/sandbox/remote_sandbox_service.py

Labels

enhancement, cloud, api

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with openhands/app_server/sandbox/remote_sandbox_service.py, especially start_sandbox and pause_old_sandboxes, then trace the /api/v1/app-conversations response path. Compare this behavior with the runtime-api rate-limit handling described in the issue. The desired behavior is not yet selected among the proposed alternatives, so completion requires an agreed API contract and corresponding coverage.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
api, cloud
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.