Summary
Proposed knowledge-base changes
For .github/workflows/shared/self-hosted-failure-modes.md, add a new row to Category A — ARC / DinD as the next free ID, A23:
| ID |
Signal |
Root cause |
Fix / flag |
Probe |
Citations |
| A23 |
On runner.topology: arc-dind with --docker-host-path-prefix set, docker compose up fails with error mounting "/dev/null" to .../home/.npmrc: create mountpoint ...: read-only file system (also seen for .docker/config.json, .composer/auth.json) |
filterAgentVolumesForSysroot() (src/services/optional-services.ts) is meant to drop the bogus AWF-owned chroot-home mount that the DinD daemon can't resolve, but it compared already-prefixed mount sources (from buildAgentVolumes(), which applies --docker-host-path-prefix as its final step) against the raw, unprefixed config.workDir/effectiveHome. Once a host-path prefix is set — always true on real ARC/DinD — the comparison silently stopped matching, so the bogus chroot-home mount survived filtering and Docker tried to create a .npmrc credential-hiding overlay mountpoint inside a path the daemon couldn't write to (EROFS). Distinct from A20 (which was about legitimate caller-supplied home mounts being dropped); A23 is the inverse case — the bogus mount not being dropped. |
Fixed in AWF (PR #7998, merged 2026-09-02): extracted prefixHostPath() in src/services/host-path-prefix.ts from translateBindMountHostPath() so bare paths can be prefixed consistently; filterAgentVolumesForSysroot() now prefixes config.workDir/effectiveHome before comparing against mount sources, restoring correct detection of daemon-invisible mounts. The existing safe fallback (dropUnbackedHostHomeOverlays, warn + skip masking) now engages correctly instead of silently failing; explicit writable --mount for the home root still preserves credential masking. Upgrade AWF to include #7998. |
Reproduce with runnerTopology: 'arc-dind' + dockerHostPathPrefix set (e.g. /host) and inspect generated compose for a .npmrc/.docker/config.json/.composer/auth.json /dev/null overlay mountpoint targeting an unprefixed effectiveHome/workDir path; on unpatched AWF, docker compose up fails with the EROFS mounting error above |
github/gh-aw#57468, #7994, #7998 |
Also add to the "Error-string quick lookup" table:
| Observable |
Likely mode |
error mounting "/dev/null" to .../home/.npmrc: create mountpoint ...: read-only file system (or .docker/config.json, .composer/auth.json) on arc-dind with --docker-host-path-prefix set |
A23 (filterAgentVolumesForSysroot() compared prefixed mount sources against unprefixed workDir/effectiveHome, so the bogus chroot-home mount wasn't dropped; fixed in #7998) |
Proposed doctor changes
For .github/workflows/self-hosted-runner-doctor.md: add the same A23 row/citation to its embedded catalog copy and the error-string lookup, worded identically to the shared-file change above, placed near the existing A20 entry (adjacent topic, distinct root cause — do not merge the two rows).
Proposed portable agent changes
For .github/agents/self-hosted-runner-doctor.md: add the matching A23 row to both its embedded catalog table and its error-string lookup section, so the portable (no-clone) agent stays in sync with the two files above.
Source issues and PRs
Note: three other awf-triage-labeled open issues touched non-hosted-runner-adjacent topics (#8016 Playwright/Chromium libs, #8015 codex context-rebuild circuit breaker, #8014 codex transient exit) but each is still speculative ("Likely..." root cause, no confirmed fix/PR yet) and not specific to self-hosted/ARC/DinD/GHES/GHEC environments — they were excluded per the narrowest-change guardrail. No open runner-doctor-labeled proposal issues currently exist.
Generated by Runner Doctor Updater · copilot · auto · 96.7 AIC · ⊞ 3.3K · ◷
Summary
Proposed knowledge-base changes
For
.github/workflows/shared/self-hosted-failure-modes.md, add a new row to Category A — ARC / DinD as the next free ID, A23:runner.topology: arc-dindwith--docker-host-path-prefixset,docker compose upfails witherror mounting "/dev/null" to .../home/.npmrc: create mountpoint ...: read-only file system(also seen for.docker/config.json,.composer/auth.json)filterAgentVolumesForSysroot()(src/services/optional-services.ts) is meant to drop the bogus AWF-owned chroot-home mount that the DinD daemon can't resolve, but it compared already-prefixed mount sources (frombuildAgentVolumes(), which applies--docker-host-path-prefixas its final step) against the raw, unprefixedconfig.workDir/effectiveHome. Once a host-path prefix is set — always true on real ARC/DinD — the comparison silently stopped matching, so the bogus chroot-home mount survived filtering and Docker tried to create a.npmrccredential-hiding overlay mountpoint inside a path the daemon couldn't write to (EROFS). Distinct from A20 (which was about legitimate caller-supplied home mounts being dropped); A23 is the inverse case — the bogus mount not being dropped.prefixHostPath()insrc/services/host-path-prefix.tsfromtranslateBindMountHostPath()so bare paths can be prefixed consistently;filterAgentVolumesForSysroot()now prefixesconfig.workDir/effectiveHomebefore comparing against mount sources, restoring correct detection of daemon-invisible mounts. The existing safe fallback (dropUnbackedHostHomeOverlays, warn + skip masking) now engages correctly instead of silently failing; explicit writable--mountfor the home root still preserves credential masking. Upgrade AWF to include #7998.runnerTopology: 'arc-dind'+dockerHostPathPrefixset (e.g./host) and inspect generated compose for a.npmrc/.docker/config.json/.composer/auth.json/dev/nulloverlay mountpoint targeting an unprefixedeffectiveHome/workDirpath; on unpatched AWF,docker compose upfails with the EROFS mounting error aboveAlso add to the "Error-string quick lookup" table:
error mounting "/dev/null" to .../home/.npmrc: create mountpoint ...: read-only file system(or.docker/config.json,.composer/auth.json) onarc-dindwith--docker-host-path-prefixsetfilterAgentVolumesForSysroot()compared prefixed mount sources against unprefixedworkDir/effectiveHome, so the bogus chroot-home mount wasn't dropped; fixed in #7998)Proposed doctor changes
For
.github/workflows/self-hosted-runner-doctor.md: add the same A23 row/citation to its embedded catalog copy and the error-string lookup, worded identically to the shared-file change above, placed near the existing A20 entry (adjacent topic, distinct root cause — do not merge the two rows).Proposed portable agent changes
For
.github/agents/self-hosted-runner-doctor.md: add the matching A23 row to both its embedded catalog table and its error-string lookup section, so the portable (no-clone) agent stays in sync with the two files above.Source issues and PRs
Note: three other
awf-triage-labeled open issues touched non-hosted-runner-adjacent topics (#8016 Playwright/Chromium libs, #8015 codex context-rebuild circuit breaker, #8014 codex transient exit) but each is still speculative ("Likely..." root cause, no confirmed fix/PR yet) and not specific to self-hosted/ARC/DinD/GHES/GHEC environments — they were excluded per the narrowest-change guardrail. No openrunner-doctor-labeled proposal issues currently exist.