Describe the bug
On 21.11 I used to have in my configuration:
systemd.services.caddy.serviceConfig = {
StateDirectory = "caddy";
Environment = "HOME=%S/caddy";
};
IIRC I did this, because otherwise Caddy would try to use / as its home directory.
When upgrading from 21.11 to 22.05 this broke, as StateDirectory = "caddy"; is now set by the caddy module itself:
$ nixos-rebuild --upgrade build
unpacking channels...
building Nix...
building the system configuration...
error: value is a string while a list was expected
at /nix/var/nix/profiles/per-user/root/channels/nixos/nixos/lib/systemd-unit-options.nix:26:14:
25| if isList (head defs'')
26| then concatLists defs''
| ^
27| else mergeEqualOption loc defs';
(use '--show-trace' to show detailed location information)
Full trace using `--show-trace`:
unpacking channels...
building Nix...
building the system configuration...
error: value is a string while a list was expected
at /nix/var/nix/profiles/per-user/root/channels/nixos/nixos/lib/systemd-unit-options.nix:26:14:
25| if isList (head defs'')
26| then concatLists defs''
| ^
27| else mergeEqualOption loc defs';
… while evaluating 'merge'
at /nix/var/nix/profiles/per-user/root/channels/nixos/nixos/lib/systemd-unit-options.nix:20:18:
19| name = "systemd option";
20| merge = loc: defs:
| ^
21| let
… from call site
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:782:59:
781| if isDefined then
782| if all (def: type.check def.value) defsFinal then type.merge loc defsFinal
| ^
783| else let allInvalid = filter (def: ! type.check def.value) defsFinal;
… while evaluating the attribute 'value'
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:793:27:
792| optionalValue =
793| if isDefined then { value = mergedValue; }
| ^
794| else {};
… while evaluating anonymous lambda
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/types.nix:432:22:
431| merge = loc: defs:
432| mapAttrs (n: v: v.value) (filterAttrs (n: v: v ? value) (zipAttrsWith (name: defs:
| ^
433| (mergeDefinitions (loc ++ [name]) elemType defs).optionalValue
… from call site
… while evaluating anonymous lambda
at /nix/var/nix/profiles/per-user/root/channels/nixos/nixos/lib/systemd-lib.nix:118:55:
117| attrsToSection = as:
118| concatStrings (concatLists (mapAttrsToList (name: value:
| ^
119| map (x: ''
… from call site
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:356:16:
355| mapAttrsToList = f: attrs:
356| map (name: f name attrs.${name}) (attrNames attrs);
| ^
357|
… while evaluating anonymous lambda
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:356:10:
355| mapAttrsToList = f: attrs:
356| map (name: f name attrs.${name}) (attrNames attrs);
| ^
357|
… from call site
… while evaluating 'attrsToSection'
at /nix/var/nix/profiles/per-user/root/channels/nixos/nixos/lib/systemd-lib.nix:117:20:
116|
117| attrsToSection = as:
| ^
118| concatStrings (concatLists (mapAttrsToList (name: value:
… from call site
at /nix/var/nix/profiles/per-user/root/channels/nixos/nixos/lib/systemd-lib.nix:367:13:
366| ${optionalString (def ? stopIfChanged && !def.stopIfChanged) "X-StopIfChanged=false"}
367| ${attrsToSection def.serviceConfig}
| ^
368| '';
… while evaluating the attribute 'value'
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:581:44:
580| defnsByName' = byName "config" (module: value:
581| [{ inherit (module) file; inherit value; }]
| ^
582| ) configs;
… while evaluating 'dischargeProperties'
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:832:25:
831| */
832| dischargeProperties = def:
| ^
833| if def._type or "" == "merge" then
… from call site
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:761:137:
760| defs' = concatMap (m:
761| map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value))
| ^
762| ) defs;
… while evaluating definitions from `/nix/var/nix/profiles/per-user/root/channels/nixos/nixos/modules/system/boot/systemd.nix':
… while evaluating anonymous lambda
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:760:28:
759| # Process mkMerge and mkIf properties.
760| defs' = concatMap (m:
| ^
761| map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value))
… from call site
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:760:17:
759| # Process mkMerge and mkIf properties.
760| defs' = concatMap (m:
| ^
761| map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value))
… while evaluating the attribute 'values'
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:873:7:
872| in {
873| values = concatMap (def: if getPrio def == highestPrio then [(strip def)] else []) defs;
| ^
874| inherit highestPrio;
… while evaluating the attribute 'values'
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:774:9:
773| in {
774| values = defs''';
| ^
775| inherit (defs'') highestPrio;
… while evaluating the attribute 'mergedValue'
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:780:5:
779| # Type-check the remaining definitions, and merge them. Or throw if no definitions.
780| mergedValue =
| ^
781| if isDefined then
… while evaluating the option `systemd.units.caddy.service.text':
… while evaluating the attribute 'value'
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:746:9:
745| in warnDeprecation opt //
746| { value = builtins.addErrorContext "while evaluating the option `${showOption loc}':" value;
| ^
747| inherit (res.defsFinal') highestPrio;
… while evaluating anonymous lambda
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:296:72:
295| # For definitions that have an associated option
296| declaredConfig = mapAttrsRecursiveCond (v: ! isOption v) (_: v: v.value) options;
| ^
297|
… from call site
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:401:20:
400| then recurse (path ++ [name]) value
401| else f (path ++ [name]) value;
| ^
402| in mapAttrs g;
… while evaluating 'g'
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:398:19:
397| g =
398| name: value:
| ^
399| if isAttrs value && cond value
… from call site
… while evaluating the attribute 'text' of the derivation 'unit-caddy.service'
at /nix/store/5dwy7n9m6l518wfccm9l7k8qj8lcxqks-nixos-22.05.956.6f637542ed0/nixos/pkgs/stdenv/generic/make-derivation.nix:278:7:
277| // (lib.optionalAttrs (attrs ? name || (attrs ? pname && attrs ? version)) {
278| name =
| ^
279| let
… while evaluating the attribute 'buildCommand' of the derivation 'system-units'
at /nix/store/5dwy7n9m6l518wfccm9l7k8qj8lcxqks-nixos-22.05.956.6f637542ed0/nixos/pkgs/stdenv/generic/make-derivation.nix:278:7:
277| // (lib.optionalAttrs (attrs ? name || (attrs ? pname && attrs ? version)) {
278| name =
| ^
279| let
… while evaluating 'check'
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/types.nix:394:15:
393| name = "path";
394| check = x: isCoercibleToString x && builtins.substring 0 1 (toString x) == "/";
| ^
395| merge = mergeEqualOption;
… from call site
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:782:22:
781| if isDefined then
782| if all (def: type.check def.value) defsFinal then type.merge loc defsFinal
| ^
783| else let allInvalid = filter (def: ! type.check def.value) defsFinal;
… while evaluating anonymous lambda
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:782:17:
781| if isDefined then
782| if all (def: type.check def.value) defsFinal then type.merge loc defsFinal
| ^
783| else let allInvalid = filter (def: ! type.check def.value) defsFinal;
… from call site
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:782:12:
781| if isDefined then
782| if all (def: type.check def.value) defsFinal then type.merge loc defsFinal
| ^
783| else let allInvalid = filter (def: ! type.check def.value) defsFinal;
… while evaluating the attribute 'mergedValue'
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:780:5:
779| # Type-check the remaining definitions, and merge them. Or throw if no definitions.
780| mergedValue =
| ^
781| if isDefined then
… while evaluating the option `environment.etc.systemd/system.source':
… while evaluating the attribute 'value'
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:746:9:
745| in warnDeprecation opt //
746| { value = builtins.addErrorContext "while evaluating the option `${showOption loc}':" value;
| ^
747| inherit (res.defsFinal') highestPrio;
… while evaluating anonymous lambda
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:296:72:
295| # For definitions that have an associated option
296| declaredConfig = mapAttrsRecursiveCond (v: ! isOption v) (_: v: v.value) options;
| ^
297|
… from call site
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:401:20:
400| then recurse (path ++ [name]) value
401| else f (path ++ [name]) value;
| ^
402| in mapAttrs g;
… while evaluating 'g'
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:398:19:
397| g =
398| name: value:
| ^
399| if isAttrs value && cond value
… from call site
… while evaluating 'escapeShellArg'
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/strings.nix:316:20:
315| */
316| escapeShellArg = arg: "'${replaceStrings ["'"] ["'\\''"] (toString arg)}'";
| ^
317|
… from call site
… while evaluating 'concatMapStringsSep'
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/strings.nix:111:5:
110| # List of input strings
111| list: concatStringsSep sep (map f list);
| ^
112|
… from call site
at /nix/var/nix/profiles/per-user/root/channels/nixos/nixos/modules/system/etc/etc.nix:54:43:
53| mkdir -p "$out/etc"
54| ${concatMapStringsSep "\n" (etcEntry: escapeShellArgs [
| ^
55| "makeEtcEntry"
… while evaluating anonymous lambda
at /nix/var/nix/profiles/per-user/root/channels/nixos/nixos/modules/system/etc/etc.nix:54:33:
53| mkdir -p "$out/etc"
54| ${concatMapStringsSep "\n" (etcEntry: escapeShellArgs [
| ^
55| "makeEtcEntry"
… from call site
… while evaluating 'concatMapStringsSep'
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/strings.nix:111:5:
110| # List of input strings
111| list: concatStringsSep sep (map f list);
| ^
112|
… from call site
at /nix/var/nix/profiles/per-user/root/channels/nixos/nixos/modules/system/etc/etc.nix:54:7:
53| mkdir -p "$out/etc"
54| ${concatMapStringsSep "\n" (etcEntry: escapeShellArgs [
| ^
55| "makeEtcEntry"
… while evaluating the attribute 'buildCommand' of the derivation 'etc'
at /nix/store/5dwy7n9m6l518wfccm9l7k8qj8lcxqks-nixos-22.05.956.6f637542ed0/nixos/pkgs/stdenv/generic/make-derivation.nix:278:7:
277| // (lib.optionalAttrs (attrs ? name || (attrs ? pname && attrs ? version)) {
278| name =
| ^
279| let
… while evaluating the attribute 'value'
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:581:44:
580| defnsByName' = byName "config" (module: value:
581| [{ inherit (module) file; inherit value; }]
| ^
582| ) configs;
… while evaluating 'atDepth'
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:60:17:
59| len = length attrPath;
60| atDepth = n:
| ^
61| if n == len
… from call site
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:63:39:
62| then value
63| else { ${elemAt attrPath n} = atDepth (n + 1); };
| ^
64| in atDepth 0;
… while evaluating the attribute 'value'
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/types.nix:461:58:
460| # Push down position info.
461| (map (def: mapAttrs (n: v: { inherit (def) file; value = v; }) def.value) defs);
| ^
462| emptyValue = { value = {}; };
… while evaluating 'dischargeProperties'
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:832:25:
831| */
832| dischargeProperties = def:
| ^
833| if def._type or "" == "merge" then
… from call site
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:761:137:
760| defs' = concatMap (m:
761| map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value))
| ^
762| ) defs;
… while evaluating definitions from `/nix/var/nix/profiles/per-user/root/channels/nixos/nixos/modules/system/etc/etc.nix':
… while evaluating anonymous lambda
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:760:28:
759| # Process mkMerge and mkIf properties.
760| defs' = concatMap (m:
| ^
761| map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value))
… from call site
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:760:17:
759| # Process mkMerge and mkIf properties.
760| defs' = concatMap (m:
| ^
761| map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value))
… while evaluating the attribute 'values'
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:873:7:
872| in {
873| values = concatMap (def: if getPrio def == highestPrio then [(strip def)] else []) defs;
| ^
874| inherit highestPrio;
… while evaluating the attribute 'values'
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:774:9:
773| in {
774| values = defs''';
| ^
775| inherit (defs'') highestPrio;
… while evaluating the attribute 'optionalValue.value'
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:792:5:
791|
792| optionalValue =
| ^
793| if isDefined then { value = mergedValue; }
… while evaluating anonymous lambda
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/types.nix:455:29:
454| merge = loc: defs:
455| zipAttrsWith (name: defs:
| ^
456| let merged = mergeDefinitions (loc ++ [name]) elemType defs;
… from call site
… while evaluating anonymous lambda
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:518:24:
517| let f = attrPath:
518| zipAttrsWith (n: values:
| ^
519| let here = attrPath ++ [n]; in
… from call site
… while evaluating the attribute 'value'
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:581:44:
580| defnsByName' = byName "config" (module: value:
581| [{ inherit (module) file; inherit value; }]
| ^
582| ) configs;
… while evaluating 'dischargeProperties'
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:832:25:
831| */
832| dischargeProperties = def:
| ^
833| if def._type or "" == "merge" then
… from call site
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:761:137:
760| defs' = concatMap (m:
761| map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value))
| ^
762| ) defs;
… while evaluating definitions from `/nix/var/nix/profiles/per-user/root/channels/nixos/nixos/modules/system/etc/etc-activation.nix':
… while evaluating anonymous lambda
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:760:28:
759| # Process mkMerge and mkIf properties.
760| defs' = concatMap (m:
| ^
761| map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value))
… from call site
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:760:17:
759| # Process mkMerge and mkIf properties.
760| defs' = concatMap (m:
| ^
761| map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value))
… while evaluating the attribute 'values'
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:873:7:
872| in {
873| values = concatMap (def: if getPrio def == highestPrio then [(strip def)] else []) defs;
| ^
874| inherit highestPrio;
… while evaluating the attribute 'values'
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:774:9:
773| in {
774| values = defs''';
| ^
775| inherit (defs'') highestPrio;
… while evaluating the attribute 'mergedValue'
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:780:5:
779| # Type-check the remaining definitions, and merge them. Or throw if no definitions.
780| mergedValue =
| ^
781| if isDefined then
… while evaluating the option `system.activationScripts.etc.text':
… while evaluating the attribute 'value'
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:746:9:
745| in warnDeprecation opt //
746| { value = builtins.addErrorContext "while evaluating the option `${showOption loc}':" value;
| ^
747| inherit (res.defsFinal') highestPrio;
… while evaluating anonymous lambda
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:296:72:
295| # For definitions that have an associated option
296| declaredConfig = mapAttrsRecursiveCond (v: ! isOption v) (_: v: v.value) options;
| ^
297|
… from call site
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:401:20:
400| then recurse (path ++ [name]) value
401| else f (path ++ [name]) value;
| ^
402| in mapAttrs g;
… while evaluating 'g'
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:398:19:
397| g =
398| name: value:
| ^
399| if isAttrs value && cond value
… from call site
… while evaluating the attribute 'text'
at /nix/var/nix/profiles/per-user/root/channels/nixos/nixos/modules/system/activation/activation-script.nix:9:5:
8| addAttributeName = mapAttrs (a: v: v // {
9| text = ''
| ^
10| #### Activation script snippet ${a}:
… while evaluating 'id'
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/trivial.nix:14:5:
13| # The value to return
14| x: x;
| ^
15|
… from call site
… while evaluating 'textClosureMap'
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/strings-with-deps.nix:75:35:
74|
75| textClosureMap = f: predefined: names:
| ^
76| concatStringsSep "\n" (map f (textClosureList predefined names));
… from call site
at /nix/var/nix/profiles/per-user/root/channels/nixos/nixos/modules/system/activation/activation-script.nix:49:9:
48|
49| ${textClosureMap id (withDrySnippets) (attrNames withDrySnippets)}
| ^
50|
… while evaluating 'systemActivationScript'
at /nix/var/nix/profiles/per-user/root/channels/nixos/nixos/modules/system/activation/activation-script.nix:20:33:
19|
20| systemActivationScript = set: onlyDry: let
| ^
21| set' = mapAttrs (_: v: if isString v then (noDepEntry v) // { supportsDryActivation = false; } else v) set;
… from call site
at /nix/var/nix/profiles/per-user/root/channels/nixos/nixos/modules/system/activation/activation-script.nix:137:18:
136| apply = set: set // {
137| script = systemActivationScript set false;
| ^
138| };
… while evaluating the attribute 'system.activationScripts.script'
at /nix/var/nix/profiles/per-user/root/channels/nixos/nixos/modules/system/activation/activation-script.nix:137:9:
136| apply = set: set // {
137| script = systemActivationScript set false;
| ^
138| };
… while evaluating the attribute 'activationScript' of the derivation 'nixos-system-web-prod-f2f8-22.05.956.6f637542ed0'
at /nix/store/5dwy7n9m6l518wfccm9l7k8qj8lcxqks-nixos-22.05.956.6f637542ed0/nixos/pkgs/stdenv/generic/make-derivation.nix:278:7:
277| // (lib.optionalAttrs (attrs ? name || (attrs ? pname && attrs ? version)) {
278| name =
| ^
279| let
So I simply dropped this from my configuration, but I feel like this should be handled better nonetheless, to:
- not expose those low-level and hard to understand internals to the user
- either provide a more meaningful error message or support changing this value
Steps To Reproduce
Steps to reproduce the behavior:
- Set
services.caddy.enable = true;
- Set
systemd.services.caddy.serviceConfig.StateDirectory = "foobar";
- Execute
nixos-rebuild build
Expected behavior
- Caddy using
StateDirectory = "foobar" for its service unit
nixos-rebuild build not failing with a hard to understand error message
Additional context
Add any other context about the problem here.
Notify maintainers
I'm not sure whether @aanderse (who did the mentioned change in the caddy module) is the right person to address here, as this could also be caused further down the line (e.g. in the systemd module) - I couldn't actually figure this out.
Metadata
[user@system:~]$ nix-shell -p nix-info --run "nix-info -m"
- system: `"x86_64-linux"`
- host os: `Linux 5.10.118, NixOS, 21.11 (Porcupine), 21.11.337814.5986ddf62ab`
- multi-user?: `yes`
- sandbox: `yes`
- version: `nix-env (Nix) 2.3.3`
- channels(root): `"nixos-22.05.956.6f637542ed0"`
- nixpkgs: `/nix/var/nix/profiles/per-user/root/channels/nixos`
Describe the bug
On 21.11 I used to have in my configuration:
IIRC I did this, because otherwise Caddy would try to use
/as its home directory.When upgrading from 21.11 to 22.05 this broke, as
StateDirectory = "caddy";is now set by the caddy module itself:Full trace using `--show-trace`:
So I simply dropped this from my configuration, but I feel like this should be handled better nonetheless, to:
Steps To Reproduce
Steps to reproduce the behavior:
services.caddy.enable = true;systemd.services.caddy.serviceConfig.StateDirectory = "foobar";nixos-rebuild buildExpected behavior
StateDirectory = "foobar"for its service unitnixos-rebuild buildnot failing with a hard to understand error messageAdditional context
Add any other context about the problem here.
Notify maintainers
I'm not sure whether @aanderse (who did the mentioned change in the caddy module) is the right person to address here, as this could also be caused further down the line (e.g. in the systemd module) - I couldn't actually figure this out.
Metadata