Cannot unmarshal bool into Go struct field InstancePut.devices of type string

I’m trying to pass a value via Salt’s lxd_container.present function, I have a block that looks kind of like this:

            path: /aux
            pool: default
            source: srv-aux
            readonly: True
            type: disk

This is then converted to JSON and passed in as a single blob under the devices directive as a device in in lxd_container.present, like so:

{{ device }}: {{ devices[device]|tojson }}

I think the error I’m getting back is from LXD however:

      Result: False
     Comment: json: cannot unmarshal bool into Go struct field InstancePut.devices of type string

I understand what the error means (“True” is not the same thing as bool True), but I’m wondering if you have any idea how I could actually pass this as a bool, or if this could be a bug.

Since there’s no strict typing in JSON or YAML that I’m aware of, I don’t really see any way for me to specify before-hand that this isn’t a string before it hits the Go binary.

That error is saying that you’re setting the devices key to a massive JSON encoded string rather than to a dict of string as is expected.

Thanks for the quick reply. If you mean that the entire configuration is wrong, I don’t think so because it works just fine when I don’t pass readonly, I probably should have been clearer on that. Or do you mean it works “by mistake” simply because all the other values are strings? How should it be passed otherwise?

According to the salt docs, devices is expected to be:

A device dict or None (None = unset).

Isn’t it possible that LXD is somehow incorrectly parsing this JSON object? If it sees an element called “readonly” coming on from a JSON object, I guess it should confidently be able to try and convert it to a bool since that’s what it’s documented as?

Or is maybe the salt module misbehaving and sending in values that should be bools as strings? I don’t know much JS but I guess you could infer that it’s a bool if it’s called True rather than "True".

Oh, I see the problem. Yeah, you want "true" here.
LXD configuration options are dict of strings, you need to make sure that all key and values are strings.

1 Like

The API spec shows the data type of each field if you click into the “model” for each request payload:

Ohh I see, the problem was actually the opposite, I guess I misread the error: it’s getting a bool but wants a string, not the other way around. Setting readonly: "true" instead fixed it. Thanks a lot, you’re a legend.

While all values passed in objects under devices are strings in the example, it does not mention that they all should be without clicking “model”, maybe that could be clarified by actually giving all attributes (including readonly) in the example?

I think I understand what you mean that < * >: string under model indicates the entire devices dict is just strings, but hopefully you can both agree that it’s a bit confusing that something explicitly listed as a bool in the documentation should be understood to be passed as a string in the API, so I don’t think some verbosity in examples would be a bad thing.

Again, thanks for your help. Much appreciated.