Skip to content

fix(acp): recover credential monitor after transient errors - #4403

Draft
simonrosenberg wants to merge 1 commit into
mainfrom
fix-acp-credential-monitor-sticky-error
Draft

fix(acp): recover credential monitor after transient errors#4403
simonrosenberg wants to merge 1 commit into
mainfrom
fix-acp-credential-monitor-sticky-error

Conversation

@simonrosenberg

@simonrosenberg simonrosenberg commented Aug 6, 2026

Copy link
Copy Markdown
Member

HUMAN:


AGENT:

Why

The Codex credential monitor permanently stopped after any CredentialSyncError, leaving a sticky error that blocked every later track_current() and flush() call. A temporary file-store or binding outage could therefore disable credential synchronization for the rest of a conversation.

This defect was identified while investigating OpenHands/enterprise#120, but this PR is a standalone defect fix independent of that issue's broader Codex-auth investigation.

Summary

  • Keep the credential monitor alive after recoverable synchronization and unexpected errors, while retaining terminal behavior for missing credentials, invalid source responses, and version conflicts.
  • Clear a recoverable sticky error after a later canonical credential read succeeds; retain authorization-rejection errors until the authorization revision changes.
  • Cover a transient write-back failure followed by successful monitor recovery, and verify persistent failures are retried after successful reads.

Issue Number

Context: https://github.com/OpenHands/enterprise/issues/120

How to Test

Automated regression and integration suites:

$ uv run pytest tests/sdk/agent/test_acp_file_credentials.py tests/agent_server/test_credential_binding.py -q
46 passed, 6 warnings in 7.12s

Repository checks:

$ uv run pre-commit run --files openhands-sdk/openhands/sdk/agent/acp_file_credentials.py tests/sdk/agent/test_acp_file_credentials.py
Ruff format..............................................................Passed
Ruff lint................................................................Passed
PEP8 style check (pycodestyle)...........................................Passed
Type check with pyright..................................................Passed
Check import dependency rules............................................Passed
Check Tool subclass registration.........................................Passed

Manual end-to-end reproduction used the real HttpVersionedCredentialBinding, a mock HTTP credential endpoint that returned 503 for the first PUT, the real file lifecycle, and its background monitor. After writing a rotated auth.json, the output was:

credential_binding_monitor_failed ... CredentialSyncError: Credential source request failed.
replace_attempts=2
monitor_alive=True
credential_synced=True

Video/Screenshots

Not applicable; this is a background credential synchronization fix. The reproduction output above shows the transient failure and successful recovery.

Type

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

Notes

The monitor remains terminal for errors that need external intervention or cannot be safely retried. No public API or configuration changes are included.


Agent Server images for this PR

GHCR package: https://github.com/OpenHands/agent-sdk/pkgs/container/agent-server

Variants & Base Images

Variant Architectures Base Image Docs / Tags
java amd64, arm64 eclipse-temurin:17-jdk Link
python amd64, arm64 nikolaik/python-nodejs:python3.13-nodejs22-slim Link
golang amd64, arm64 golang:1.21-bookworm Link

Pull (multi-arch manifest)

# Each variant is a multi-arch manifest supporting both amd64 and arm64
docker pull ghcr.io/openhands/agent-server:7cac175-python

Run

docker run -it --rm \
  -p 8000:8000 \
  --name agent-server-7cac175-python \
  ghcr.io/openhands/agent-server:7cac175-python

All tags pushed for this build

ghcr.io/openhands/agent-server:7cac175-golang-amd64
ghcr.io/openhands/agent-server:7cac175ec257eb6d55adc2dc39d566960af5b7d4-golang-amd64
ghcr.io/openhands/agent-server:fix-acp-credential-monitor-sticky-error-golang-amd64
ghcr.io/openhands/agent-server:7cac175-golang_tag_1.21-bookworm-amd64
ghcr.io/openhands/agent-server:7cac175-golang-arm64
ghcr.io/openhands/agent-server:7cac175ec257eb6d55adc2dc39d566960af5b7d4-golang-arm64
ghcr.io/openhands/agent-server:fix-acp-credential-monitor-sticky-error-golang-arm64
ghcr.io/openhands/agent-server:7cac175-golang_tag_1.21-bookworm-arm64
ghcr.io/openhands/agent-server:7cac175-java-amd64
ghcr.io/openhands/agent-server:7cac175ec257eb6d55adc2dc39d566960af5b7d4-java-amd64
ghcr.io/openhands/agent-server:fix-acp-credential-monitor-sticky-error-java-amd64
ghcr.io/openhands/agent-server:7cac175-eclipse-temurin_tag_17-jdk-amd64
ghcr.io/openhands/agent-server:7cac175-java-arm64
ghcr.io/openhands/agent-server:7cac175ec257eb6d55adc2dc39d566960af5b7d4-java-arm64
ghcr.io/openhands/agent-server:fix-acp-credential-monitor-sticky-error-java-arm64
ghcr.io/openhands/agent-server:7cac175-eclipse-temurin_tag_17-jdk-arm64
ghcr.io/openhands/agent-server:7cac175-python-amd64
ghcr.io/openhands/agent-server:7cac175ec257eb6d55adc2dc39d566960af5b7d4-python-amd64
ghcr.io/openhands/agent-server:fix-acp-credential-monitor-sticky-error-python-amd64
ghcr.io/openhands/agent-server:7cac175-nikolaik_s_python-nodejs_tag_python3.13-nodejs22-slim-amd64
ghcr.io/openhands/agent-server:7cac175-python-arm64
ghcr.io/openhands/agent-server:7cac175ec257eb6d55adc2dc39d566960af5b7d4-python-arm64
ghcr.io/openhands/agent-server:fix-acp-credential-monitor-sticky-error-python-arm64
ghcr.io/openhands/agent-server:7cac175-nikolaik_s_python-nodejs_tag_python3.13-nodejs22-slim-arm64
ghcr.io/openhands/agent-server:7cac175-golang
ghcr.io/openhands/agent-server:7cac175ec257eb6d55adc2dc39d566960af5b7d4-golang
ghcr.io/openhands/agent-server:fix-acp-credential-monitor-sticky-error-golang
ghcr.io/openhands/agent-server:7cac175-golang_tag_1.21-bookworm
ghcr.io/openhands/agent-server:7cac175-java
ghcr.io/openhands/agent-server:7cac175ec257eb6d55adc2dc39d566960af5b7d4-java
ghcr.io/openhands/agent-server:fix-acp-credential-monitor-sticky-error-java
ghcr.io/openhands/agent-server:7cac175-eclipse-temurin_tag_17-jdk
ghcr.io/openhands/agent-server:7cac175-python
ghcr.io/openhands/agent-server:7cac175ec257eb6d55adc2dc39d566960af5b7d4-python
ghcr.io/openhands/agent-server:fix-acp-credential-monitor-sticky-error-python
ghcr.io/openhands/agent-server:7cac175-nikolaik_s_python-nodejs_tag_python3.13-nodejs22-slim

About Multi-Architecture Support

  • Each variant tag (e.g., 7cac175-python) is a multi-arch manifest supporting both amd64 and arm64
  • Docker automatically pulls the correct architecture for your platform
  • Individual architecture tags (e.g., 7cac175-python-amd64) are also available if needed

Co-authored-by: openhands <openhands@all-hands.dev>
@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Coverage

Coverage Report •
FileStmtsMissCoverMissing
openhands-sdk/openhands/sdk/agent
   acp_file_credentials.py3455684%76–77, 86, 92, 138–140, 155–158, 170, 176, 204, 254–255, 259–260, 263, 269, 272–273, 280, 290–291, 293–294, 310, 316–319, 323, 348, 360, 366–367, 370–373, 378–379, 382–385, 396, 401–402, 409–410, 420, 458–459, 490
TOTAL393301117172% 

@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Python API breakage checks — ✅ PASSED

Result:PASSED

Action log

@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

REST API breakage checks (OpenAPI) — ✅ PASSED

Result:PASSED

Action log

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