OpenHands / OpenHands/software-agent-sdk

[Bug]: OpenHandsCloudWorkspace resume leaves the active client on stale connection data

Open
#4,664 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

architecture bug priority:medium ready-for-dev security workspace
Dominant language
Python
Stars
1.1k
Forks
539
Avg merge
1d 19h
Merged PRs (30d)
137

Description

Bug Description

Cloud readiness polling refreshes _session_api_key and exposed URLs (openhands-workspace/openhands/workspace/cloud/workspace.py:361-374). Initial startup copies those values into inherited host/api_key and resets the remote client (:242-300). Public resume() polls readiness again (:444-458) but does not reapply the refreshed URL/key or reset the cached client.

After a sandbox returns with a rotated key or changed exposed URL, settings/skills calls can use the refreshed private key while normal workspace/conversation calls retain stale inherited headers and endpoint. The object can describe two different connections at once.

Expected Behavior

A RUNNING sandbox should have one atomic agent-server connection: endpoint, session key, inherited API key, and cached client must agree after startup and resume.

Actual Behavior

An independent, self-contained reproducer is posted in the issue comments. Save
it as /tmp/repro_4664.py, then run:

uv run python /tmp/repro_4664.py

On SDK commit bc5dfc50d, it exercises the real resume, readiness, and HTTP-client paths; only the external Cloud API and health-check boundaries are represented by a fixture and prints:

discovered_url=https://new-agent.example.com
active_host=https://old-agent.example.com
discovered_session_key=new-session-key
active_api_key=old-session-key
client_reused=True
client_base_url=https://old-agent.example.com
client_session_key=old-session-key
Suggested Implementation

Extract one private “apply ready connection” helper or immutable connection snapshot and use it after both initial readiness and resume. Apply host and api_key together, then reset/rebuild the client. Prefer the inherited API key as the single credential source once connected.

Acceptance Criteria
  • Resume with a changed exposed URL routes subsequent calls to the new endpoint.
  • Resume with a rotated session key sends the new X-Session-API-Key for command, settings, and skills calls.
  • Initial provisioned/local modes and missing-key behavior remain unchanged.
  • Cleanup clears one coherent connection state.
  • Public workspace constructor and remote API contracts remain unchanged.
Version

Current main at 6d3881035. Existing issue search found no duplicate.

Contributor guide

Open the contributing guide

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 in openhands-workspace/openhands/workspace/cloud/workspace.py, especially the initial readiness flow at lines 242-300 and refresh logic at 361-374, then compare it with public resume() at 444-458. Run /tmp/repro_4664.py with uv to observe the stale host, key, and client. Done means startup and resume keep the endpoint, credentials, inherited fields, and cached client consistent while preserving the listed mode, cleanup, and API-contract behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
api, backend, cloud
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.