OpenHands / OpenHands/enterprise
[Feature/Bug]: Cloud API should return rate limit error (429) instead of silently pausing existing runtimes
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:
- A rate limit error (HTTP 429) when they exceed their limit, OR
- 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-conversationsendpoint - 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
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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