Found while fixing #642 (PR #643). Same error shape, different producer pair; not fixed by that PR.
Symptom
Two custom forward classes chained — inner → mid, then mid → homeManager:
error: The option `home-manager.users.tux.den.fwd."inner/mid/programs/bash"'
is already declared in `…/flake.nix'.
The collision is on the inner hop's declaration, not the one PR #643 suppresses.
Repro
test-chained-forward-with-host-aspects = denTest (
{ den, lib, tuxHm, ... }:
let
innerClass =
{ class, aspect-chain }:
den._.forward {
each = lib.singleton class;
fromClass = _: "inner";
intoClass = _: "mid";
intoPath = _: [ "programs" "bash" ];
fromAspect = _: lib.last aspect-chain;
guard = _: true;
};
midClass =
{ class, aspect-chain }:
den._.forward {
each = lib.singleton class;
fromClass = _: "mid";
intoClass = _: "homeManager";
intoPath = _: [ ];
fromAspect = _: lib.last aspect-chain;
};
in
{
den.default.includes = [ den._.host-aspects innerClass midClass ];
den.aspects.chained.inner.enable = true;
den.hosts.x86_64-linux.igloo.users.tux = { };
den.aspects.tux.includes = [ den.aspects.chained ];
expr = tuxHm.programs.bash.enable or "<stranded>";
expected = true;
}
);
Attribution
PR #643 leaves the parent pipeline's copy as the single owner for routes whose declaration lands in the spawn's extracted class. For an intermediate custom class the declaration lands in another bucket first and reaches the target through the second hop, so a second producer survives.
Found while fixing #642 (PR #643). Same error shape, different producer pair; not fixed by that PR.
Symptom
Two custom forward classes chained —
inner → mid, thenmid → homeManager:The collision is on the inner hop's declaration, not the one PR #643 suppresses.
Repro
Attribution
The option home-manager.users.tux.programs.chained does not exist, showing the chained content does arrive. The defect is purely the duplicated declaration.PR #643 leaves the parent pipeline's copy as the single owner for routes whose declaration lands in the spawn's extracted class. For an intermediate custom class the declaration lands in another bucket first and reaches the target through the second hop, so a second producer survives.