agentscope-ai / agentscope-ai/AgentTeams

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

Aperta
#711 4 commenti 0 reazioni 1 assegnatario Rivendicata da @maplefeng-a Vedi su GitHub
area:worker-runtime
Lingua principale
Go
Stelle
5.6k
Fork
692
Merge medio
5g 4h
PR unite (30g)
23

Descrizione

## 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).

Guida per i contributori

Nessuna guida per i contributori indicizzata per questo repository

Valutazione

Questa issue non è ancora stata valutata.

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.