agentscope-ai / agentscope-ai/AgentTeams

[Bug] copaw worker can crash reading partially-written merged AGENTS.md during apply --zip update

オープン
#711 コメント 4 件 リアクション 0 件 担当者 1 名 @maplefeng-a が担当を希望しています GitHub で見る
area:worker-runtime
主要言語
Go
スター
5.6k
フォーク
692
平均マージ
5日 4時間
マージ済み PR(30日)
23

説明

## Summary

`copaw/src/copaw_worker/worker.py:123` reads `AGENTS.md` from
`self.sync.local_dir` via `read_text()` with no retry or size check.
On `hiclaw apply worker --zip` against an **existing** copaw worker
(update path), this read appears to race with the sync's merged-file
write, producing `UnicodeDecodeError` mid multi-byte character; the
container exits with code 1 and only recovers on a manual
`docker start`.

## Environment

- HiClaw v1.1.0 GA, embedded mode, macOS Docker Desktop
- Worker: copaw runtime, package contains `config/SOUL.md` + `config/AGENTS.md`
- Reproduces on `apply --zip` *update* (existing worker), not on initial create

## Reproduction

1. Have a copaw worker already running with package A
2. Build package B with a modified `config/AGENTS.md`
3. `docker cp B.zip hiclaw-controller:/tmp/`
4. `docker exec hiclaw-controller hiclaw apply worker --zip /tmp/B.zip --name `
5. Within ~10s: `docker ps -a --filter name=hiclaw-worker-` shows `Exited (1)`

## Observed traceback (excerpt)

```
File ".../copaw_worker/worker.py", line 123, in start
(workspace_dir / name).write_text(src.read_text())
File ".../pathlib.py", line 1059, in read_text
return f.read()
UnicodeDecodeError: 'utf-8' codec can't decode bytes in position 19964-19965:
unexpected end of data
```

## Investigation (evidence, not proof)

The race-with-sync explanation is the most consistent reading of the
evidence, but I have not done a source-level confirmation that the two
writers/readers actually overlap. What we observed:

- The merged `agents//AGENTS.md` in MinIO **is** valid UTF-8
when fetched post-mortem (`mc cp ...` after the crash; complete +
decodable end-to-end)
- File size at the error position (~19964 bytes) is suspiciously
close to the *previous* merged file size, consistent with
`worker.start()` reading partway into the new prefix during the
merger's write
- `docker start ` recovers cleanly; second boot sees the
fully-written file

## Suggested directions

1. **Atomic merge writes** — write the merged file to `*.tmp` then
`os.replace`, so partial reads are structurally impossible. Most
robust: addresses the root cause regardless of who reads when
2. **Bounded retry on `UnicodeDecodeError`** in `worker.py:123` —
surgical fallback that hardens the read site without changing the
sync side
3. Explicit "sync ready" signal that `worker.start()` waits on

(1) seems cleanest as a primary fix; (2) is reasonable defense-in-depth.

## Workaround (current)

After `apply --zip` update, wait ~10s. If the worker container shows
`Exited (1)`, run `docker start `. Second boot
succeeds because the merge is complete on disk by then. This is what
we currently document for our deployment (haopaw).

コントリビューションガイド

このリポジトリのコントリビューションガイドは索引されていません

評価

この issue はまだ評価されていません。

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。