Skip to content

fix(agent-server): fall back to shared workspace on unborn worktree base - #6216

Open
xxwtiancai wants to merge 2 commits into
OpenHands:mainfrom
xxwtiancai:fix/child-launch-unborn-worktree-6186
Open

xxwtiancai wants to merge 2 commits into
OpenHands:mainfrom
xxwtiancai:fix/child-launch-unborn-worktree-6186

Conversation

@xxwtiancai

@xxwtiancai xxwtiancai commented Oct 25, 2026 •

Copy link
Copy Markdown

HUMAN:

Problem: Launching a child workspace on an unborn HEAD fails with an unhandled HTTP 500 error.

Fix: Resolves the default base ref first, falling back to shared workspace on unborn HEADs while keeping explicit ref errors strict.

Verification: Verified against live server regression: child launch succeeds with HTTP 201 and isolation: "shared" without fake commits.


AGENT:

Why

A normal parent conversation in an empty workspace initializes Git without making a commit. Creating a child with the default worktree isolation then failed with HTTP 500: the worktree planner accepted the repository, but git worktree add ... HEAD cannot branch from an unborn HEAD. Explicit isolation: shared avoided the failure, so only the default path was broken. Fixes #6186.

Summary

  • _plan_conversation_worktree now resolves the worktree start point at plan time and, for the default base="default_branch", verifies it resolves to a commit (git rev-parse --verify --quiet <ref>^{commit}). Exit code 1 — the unborn HEAD of a repository initialized without a commit — produces no plan, so conversation creation uses the existing shared-workspace fallback and the response reports isolation: "shared". Any other git failure still propagates, so other Git errors are not silently treated as an empty repository.
  • Explicit base="head" / base="ref" keep their current error semantics; a missing explicitly requested ref remains an error.
  • The plan now carries the selected ref (not a re-resolution at creation time, and not a resolved hash), so git worktree add preserves remote branch tracking configuration on the new branch.
  • Updated the isolation field descriptions in StartChildConversationRequest and the start_child_conversation tool to say "git repository with a usable base commit". The TypeScript client's generated schema intentionally stays untouched here — it is generated from the pinned released Agent Server image and is refreshed by the post-release version-bump workflow.

Issue Number

Fixes #6186

How to Test

uv run --frozen pytest \
  tests/cross/test_remote_conversation_live_server.py::test_child_launch_in_fresh_workspace_preserves_unborn_repository \
  "tests/agent_server/test_conversation_service.py::TestConversationServiceStartConversation" \
  tests/agent_server/test_parent_child_conversations.py \
  tests/tools/child_conversation -q

New coverage (the live-server test and the unborn-HEAD planner test both fail with the original GitCommandError: git worktree add ... HEAD / HTTP 500 before the change and pass after):

  • test_child_launch_in_fresh_workspace_preserves_unborn_repository (real HTTP server): fresh parent → .git exists with unborn HEAD → default child launch returns 201 with isolation: "shared" and the parent link; no initial commit is invented and the pre-existing file plus unborn repository survive child launch and cleanup.
  • Planner unit tests: unborn HEAD with no remote/main/master → no plan; a usable remote default branch on an unborn local repo → plan with start_point == "origin/<default>" (worktree isolation retained); explicit base="head" on an unborn repo → plan still produced and _create_conversation_worktree still raises (current semantics preserved).

Full files pass after the change: tests/agent_server/test_conversation_service.py (141), tests/cross/test_remote_conversation_live_server.py (34 passed, 1 skipped), tests/agent_server/test_parent_child_conversations.py + tests/tools/child_conversation (31). Pre-commit (ruff, pycodestyle, pyright, import rules) passes on all changed files.

Video/Screenshots

Non-visual bug; reproduction notes instead of media:

  • Before the change, the live-server test fails with the issue's original symptom: POST /api/conversations/{id}/children → HTTP 500 from git worktree add -b openhands/<child-id> ... HEAD (fatal: invalid reference: HEAD).
  • After the change, the same workflow returns 201 with isolation: "shared".

Type

  • Bug fix
  • Feature
  • Refactor
  • Breaking change
  • Docs / chore

A context-window-rejected agent call emits a CondensationRequest and the
condenser answers with a Condensation, but nothing ever stopped that
cycle: _is_stuck_context_window_error was an unconditional stub, so a
conversation whose prompt never fits kept burning one rejected agent
call plus one summarizer call per iteration until max_iteration_per_run.

Implement the detection: the run is stuck when every event in the
trailing window after the last user message belongs to such
rejected-call/condensation cycles, with at least one
CondensationRequest (which proactive token/event-pressure condensation
does not emit) and no action, observation, or agent message between
them. The existing 10-event scenario gate and the STUCK run-loop exit
bound the detection; a user message still resets the window.

Fixes OpenHands#6104
A fresh parent conversation initializes its workspace as a git repository
without committing, so HEAD is unborn. The worktree planner accepted the
repository anyway and `git worktree add ... HEAD` failed with HTTP 500 on
the default child launch, instead of using the existing shared-workspace
fallback.

The planner now resolves the worktree start point and, for the default
base, verifies it resolves to a commit: an unborn HEAD (exit code 1)
produces no plan, so the child shares the parent's directory and reports
isolation "shared". Explicit head/ref bases keep their current error
semantics, any other git failure still propagates, and the plan carries
the selected ref (not a resolved hash) so remote branch tracking
configuration survives.

Fixes OpenHands#6186
@xxwtiancai
xxwtiancai marked this pull request as ready for review October 25, 2026 09:17
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.

[Bug]: Default child launch fails in a newly initialized workspace

1 participant