JDK_JAVA_OPTIONS in the environment breaks Mill's daemon RPC, reported as 'Worker wire broken' #494

Open
opened 2026-09-01 15:32:30 +00:00 by mph · 3 comments
Owner

Found triaging IW-436 (LESSONS.md entry 5). Blocked the whole of IW-436 Phase 2.

Every ./mill and ./iw invocation failed with:

java.lang.IllegalStateException: Worker wire broken, worker likely crashed. Connection DaemonRpcClient

out/mill-daemon/server.log shows the real cause on the server side:

connection handler ... error: upickle.core.TraceVisitor$TraceException: $
Caused by: ujson.ParseException: expected json value got "G" at index 0

Root cause

The daemon reads non-JSON on the RPC wire. The environment has JDK_JAVA_OPTIONS=-XX:MaxRAMPercentage=10 set, which makes every JVM Mill spawns print NOTE: Picked up JDK_JAVA_OPTIONS: ... on start-up. That line lands on the pipe the daemon parses as JSON.

Confirmed by bisection, both directions:

  • env -u JDK_JAVA_OPTIONS ./mill show core.jar — succeeds.
  • ./mill --no-daemon show core.jar — succeeds, and prints the NOTE: line in its own output where it is harmless.
  • ./mill show core.jar with the variable set — fails every time, on a fresh out/mill-daemon as well as an existing one.

Why it matters

This is an environment fault, not an iw-cli defect, but it is invisible in the launcher's own error text — the launcher reports a crashed worker and says nothing about the wire content. A developer who hits this has no path from the message to the cause without reading out/mill-daemon/server.log.

Workaround used for the whole of IW-436 Phase 2: prefix every build command with env -u JDK_JAVA_OPTIONS.

Wanted

  • ./mill and ./iw survive a set JDK_JAVA_OPTIONS — the wrapper can unset it for the daemon launch.
  • The failure text points at out/mill-daemon/server.log.

#443 records the same family — a long-lived build daemon failing as something other than what it reports — and names "the first was Mill's worker: Worker wire broken, worker likely crashed" without finding the cause. This issue is that cause.

Found triaging IW-436 (LESSONS.md entry 5). Blocked the whole of IW-436 Phase 2. Every `./mill` and `./iw` invocation failed with: ``` java.lang.IllegalStateException: Worker wire broken, worker likely crashed. Connection DaemonRpcClient ``` `out/mill-daemon/server.log` shows the real cause on the server side: ``` connection handler ... error: upickle.core.TraceVisitor$TraceException: $ Caused by: ujson.ParseException: expected json value got "G" at index 0 ``` ## Root cause The daemon reads non-JSON on the RPC wire. The environment has `JDK_JAVA_OPTIONS=-XX:MaxRAMPercentage=10` set, which makes **every JVM Mill spawns** print `NOTE: Picked up JDK_JAVA_OPTIONS: ...` on start-up. That line lands on the pipe the daemon parses as JSON. Confirmed by bisection, both directions: - `env -u JDK_JAVA_OPTIONS ./mill show core.jar` — succeeds. - `./mill --no-daemon show core.jar` — succeeds, and prints the `NOTE:` line in its own output where it is harmless. - `./mill show core.jar` with the variable set — fails every time, on a fresh `out/mill-daemon` as well as an existing one. ## Why it matters This is an environment fault, not an iw-cli defect, but it is invisible in the launcher's own error text — the launcher reports a crashed worker and says nothing about the wire content. A developer who hits this has no path from the message to the cause without reading `out/mill-daemon/server.log`. Workaround used for the whole of IW-436 Phase 2: prefix every build command with `env -u JDK_JAVA_OPTIONS`. ## Wanted - `./mill` and `./iw` survive a set `JDK_JAVA_OPTIONS` — the wrapper can unset it for the daemon launch. - The failure text points at `out/mill-daemon/server.log`. ## Related #443 records the same family — a long-lived build daemon failing as something other than what it reports — and names "the first was Mill's worker: `Worker wire broken, worker likely crashed`" without finding the cause. **This issue is that cause.**
Member

Intake: agent-ready
Workflow: diagnostic
Reason: all gates passed
Analysis: project-management/issues/IW-494/analysis.md on branch IW-494

Intake: agent-ready Workflow: diagnostic Reason: all gates passed Analysis: project-management/issues/IW-494/analysis.md on branch IW-494
Member

Implement: needs-human
Reason: batch-implement exit 1 — the kanon plugin did not compile against the core of this branch, so no phase ran

main changed the tracker port to return Either[TrackerError, …] (#778, #780). The installed kanon plugin still expects Either[String, …] at lib/batch/ForgeCatchUp.scala:143. This failure is not specific to this issue: every iw-cli issue stops at the same point until the plugin agrees with the core again. No batch-implement.log was written. The output of the command:

[warn]  Using directives detected in multiple files:
- /home/mph/.local/share/iw/plugins/kanon/lib/deps.scala:1:1-7:41
It is recommended to keep them centralized in the /home/mph/Devel/iw/iw-cli-IW-494/core/project.scala file.

[error] /home/mph/.local/share/iw/plugins/kanon/lib/batch/ForgeCatchUp.scala:143:7
[error] Found:    Either[iw.core.model.TrackerError, Option[batch.ForgeState]]
[error] Required: Either[String, Option[batch.ForgeState]]
Compilation failed
Implement: needs-human Reason: batch-implement exit 1 — the kanon plugin did not compile against the core of this branch, so no phase ran `main` changed the tracker port to return `Either[TrackerError, …]` (#778, #780). The installed kanon plugin still expects `Either[String, …]` at `lib/batch/ForgeCatchUp.scala:143`. This failure is not specific to this issue: every iw-cli issue stops at the same point until the plugin agrees with the core again. No `batch-implement.log` was written. The output of the command: ``` [warn] Using directives detected in multiple files: - /home/mph/.local/share/iw/plugins/kanon/lib/deps.scala:1:1-7:41 It is recommended to keep them centralized in the /home/mph/Devel/iw/iw-cli-IW-494/core/project.scala file. [error] /home/mph/.local/share/iw/plugins/kanon/lib/batch/ForgeCatchUp.scala:143:7 [error] Found: Either[iw.core.model.TrackerError, Option[batch.ForgeState]] [error] Required: Either[String, Option[batch.ForgeState]] Compilation failed ```
Member

Release: the implement loop failed this issue for a reason outside it. The kanon plugin did not compile against iw-cli main, because the tracker port now returns TrackerError (iw-cli #778). The plugin fix is dev-docs #484, and iw-cli 0.22.1 carries the core change. The issue goes back to the implement loop.

Release: the implement loop failed this issue for a reason outside it. The kanon plugin did not compile against iw-cli main, because the tracker port now returns TrackerError (iw-cli #778). The plugin fix is dev-docs #484, and iw-cli 0.22.1 carries the core change. The issue goes back to the implement loop.
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
iterative-works/iw-cli#494
No description provided.