--- id: "bug-1556" status: "fixed" status_updated: "2026-09-24" status_note: "" component: "xceadmin" severity: "unknown" timestamp: "2026-08-13T07:41:00Z" last_seen: "2026-09-19T09:00:00Z" occurrences: 1 files: ["src/xceadmin/src/xcecommon/mapping.py"] tags: ["xceadmin", "config", "scheduling", "wire-encoding", "high-severity"] related: [] legacy: true --- # bug-1556: Every host using the documented hosts.yaml default (no max_slot, meaning 'auto-detect from CPU… ## Description Every host using the documented hosts.yaml default (no max_slot, meaning 'auto-detect from CPU count') gets 0 scheduling slots -- permanently blocks the scheduler from placing any job on that host ## Environment _Not recorded (migrated from buglog.json)._ ## Reproduction _Not recorded (migrated from buglog.json)._ ## Root cause hosts.schema.json documents max_slot: -1 as the 'auto-detect' sentinel, but HostConfig.mxj is UInt32 on the wire and cannot represent -1 (pycapnp raises capnp.KjException for a negative assignment). mapping.py's _build_host_config() worked around this by leaving mxj unset when max_slot was absent/negative, which capnp defaults to 0. worker.c's apply_join_state() then does `nslots = hconfig->mxj; if (nslots < 0) nslots = maxcpus;` -- but 0 is never < 0, so the auto-detect fallback never fires, and the host is explicitly configured with 0 slots. Confirmed live via a real deploy: resval -n slots showed value: 0.000000 for the default host. An existing test (test_mapping.py) even asserted this broken behavior as correct (`assert h.mxj == 0`). ## Fix mapping.py now sets mxj = HOSTCONFIG_MXJ_AUTO_DETECT (0xFFFFFFFF) instead of leaving it unset. The controller's `int mxj` field receives this via capn_read32()'s implicit uint32_t->int conversion, which reinterprets it back to -1 on this project's two's-complement target platforms -- no capnp schema change or C-side change needed, apply_join_state()'s existing `nslots<0` fallback already handles a genuine -1 correctly (now proven by a new C regression test, test_apply_join_state_mxj_negative_one_falls_back_to_maxcpus, since no existing test exercised that branch with a negative mxj before). Updated the stale test assertion, added a new test for the absent-max_slot production case, and regenerated the xceadmin golden fixture (tests/fixtures/full/expected.bin) whose wire bytes changed as a result. ## Verification _Not recorded (migrated from buglog.json)._ ## References _Not recorded (migrated from buglog.json)._