Null ValueTree error but ValueTree exists?

I have a ValueTree (patch) with a subtree (named “KEYLOCK”). I’d like to change the property “DEFAULTLOCK” of “KEYLOCK” when a toggle button is pressed, but I’m failing an assertion when I try to do so: “Trying to add a property to a null ValueTree will fail.” The weird thing is that, as far as I can tell, all ValueTrees in question appear to exist!

The following code prints the correct value of the property “DEFAULTLOCK” (set elsewhere in the code), but when I try to set it here I get the jassert.

juce::Logger::writeToLog(patch.getChildWithName(patchName).getProperty("DEFAULTLOCK") ? "true" : "false");
patch.getChildWithName(patchName).setProperty("DEFAULTLOCK", defaultLockButton.getToggleState(), nullptr);

Any ideas for what might be going on? Thank you!

has the parent value tree you tried to add the property to been made valid yet? you can validate a valueTree by giving it an identifier (juce::String / juce::Identifier) at construction

As far as I can tell, the parent value tree is valid: it has other child valuetrees which work as expected elsewhere. It also works here to read properties, but for some reason isn’t working to set them here.

Thank you!

The class might be a normal initialised ValueTree, but like @Mrugalla pointed out: a ValueTree is considered invalid when it was constructed from the default constructor.
When you created the parent ValueTree, make sure to give it a type name:

juce::ValueTree patch;              // <= invalid
juce::ValueTree patch ("");         // <= invalid
juce::ValueTree patch ("whatever"); // <= valid

You seem to be able to use an invalid ValueTree, but in some functions there is a check to warn you that the ValueTree might not do what you expect.

Hope that helps

what daniel says.

also it could be that at some point of your code you actually replaced a valid vt with an invalid one accidently. that would explain why it seems that some stuff works

I think I figured it out; I was initializing the child ValueTree with a juce::Identifier&, but the Identifier was going out of scope before the ValueTree was accessed. Switching this to an object instead of a reference so that it made a copy of the original Identifier fixed this.

Thank you very much for the help!

Hi !
I’m having the same problem. I have a juce::ValueTree as a member of my Processor to store filepaths of impulse responses, I call its constructor in the initializer list of my Processor

Processor::Processor()
#ifndef JucePlugin_PreferredChannelConfigurations
     : AudioProcessor (BusesProperties()
                     #if ! JucePlugin_IsMidiEffect
                      #if ! JucePlugin_IsSynth
                       .withInput  ("Input",  juce::AudioChannelSet::stereo(), true)
                      #endif
                       .withOutput ("Output", juce::AudioChannelSet::stereo(), true)
                     #endif
                       )
#endif
,
apvts(*this, nullptr, juce::Identifier("Params"), createParameterLayout()),
valueTree(juce::Identifier("IR_PATHS"))
{ ...

The valueTree seems to be valid to me (or I’m missing a part), but as soon as I get into the Processor::prepareToPlay() method, the valueTree is invalid (in the VS debugger), and when i try to store a String in it I get the jassert(object != nullptr).

I even tried to store the Identifier as a member of the Processor to make sure it does not get destroyed but nope.

What am I missing ?
Thanks in advance.

I think your issue is different than mine was, mine had to do with passing an Identifier to the constructor, and the issue was that it only existed in the scope of the constructor.

I’m not sure why it isn’t working for you even when you store the Identifier as member of the processor, but if I remember correctly, you should be able to initialize valueTree with just a string, which it will turn into an Identifier internally. So just valueTree("IR_PATHS").

Hopefully this helps, I’m a bit rusty with JUCE.

Hi !
I found what was the problem, the valueTree was properly created and stored in the constructor, but when setStateInformation is called, a new apvts (that does not contains valueTree as a child) is read from disk and thus when I do valueTree = apvts.getChildWithName(“name”) it does not exists as it has never been stored before and thus is now a nullptr. Essentially the apvts is overwritten in setStateInformation().

What to do then is to delete the cached information (delete Appdata/Roaming/name_of_the_program on Windows), load the program and properly close is letting it go through getStateInformation where you then append the valueTree to the apvts and storing them to disk. Now the valueTree is stored and will be properly loaded on next launch.

Hope this is clear and will help people with the same problem.