Both warnings and assertions can be defined using the <xreflinkend="opt-_module.assertions"/> option. Each assertion needs an attribute name, under which you have to define an enable condition using <xreflinkend="opt-_module.assertions._name_.enable"/> and a message using <xreflinkend="opt-_module.assertions._name_.message"/>. Note that the enable condition is <emphasis>inverse</emphasis> of what an assertion would be: To assert a value being true, the enable condition should be false in that case, so that it isn't triggered. For the assertion message, you can add <literal>options</literal> to the module arguments and use <literal>${options.path.to.option}</literal> to print a context-aware string representation of the option path. Here is an example showing how this can be done.
Sometimes you can get warnings or assertions that don't apply to your specific case and you wish to ignore them, or at least make assertions non-fatal. You can do so for all assertions defined using <xreflinkend="opt-_module.assertions"/> by using the attribute name of the definition, which is conveniently printed using <literal>[...]</literal> when the assertion is triggered. For above example, the evaluation output when the assertions are triggered looks as follows:
</para>
<programlisting>
trace: warning: [grafanaPassword] The grafana password defined with
services.grafana.database.password will be stored as plaintext in the Nix store!
error: Failed assertions:
- [gpgSshAgent] You can't enable both programs.ssh.startAgent and
The <literal>[grafanaPassword]</literal> and <literal>[gpgSshAgent]</literal> strings tell you that these were defined under the <literal>grafanaPassword</literal> and <literal>gpgSshAgent</literal> attributes of <xreflinkend="opt-_module.assertions"/> respectively. With this knowledge you can adjust them to your liking:
<title>Warnings and Assertions in Submodules</title>
<para>
Warnings and assertions can be defined within submodules in the same way. Here is an example:
</para>
<programlisting>
{ lib, ... }: {
options.myServices = lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule ({ config, options, ... }: {
options.port = lib.mkOption {};
config._module.assertions.portConflict = {
enable = config.port == 80;
message = "Port ${toString config.port} defined using"
+ " ${options.port} is usually used for HTTP";
type = "warning";
};
}));
};
}
</programlisting>
<para>
When this assertion is triggered, it shows both the submodule path along with the assertion attribute within that submodule, joined by a <literal>/</literal>. Note also how <literal>${options.port}</literal> correctly shows the context of the option.
</para>
<programlisting>
trace: warning: [myServices.foo/portConflict] Port 80 defined using
myServices.foo.port is usually used for HTTP
</programlisting>
<para>
Therefore to disable such an assertion, you can do so by changing the <xreflinkend="opt-_module.assertions"/> option within the <literal>myServices.foo</literal> submodule: