Crash when loading VST2 if VST3 is present

My project has JUCE_VST3_CAN_REPLACE_VST2 = 1 set (not sure if it’s relevant).

  • When I load the VST3 version of my plugin in Cubase, everything works fine.
  • However, if I try to load the VST2 version, Cubase crashes.
  • If I delete the VST3 version, the VST2 plugin loads without issues.

I’m on an M1, so I have to run Cubase in Rosetta mode and can’t attach a debugger to the VST2 plugin. But the same issue occurs on Intel Macs and Windows as well.

Has anyone else experienced this?

For reference, in Reaper, both VST2 and VST3 versions can coexist without any problems.

It seems that in Cubase, VST2 won’t load if the VST3 version is present. The only way to use VST2 is to delete the VST3 plugin.

Here is the crashlog:

Thread 0 Crashed::  Dispatch queue: com.apple.main-thread  
0   Instrument Name            	       0x1b18643c1 juce::JuceVST3EditController::setComponentState(Steinberg::IBStream*) + 337  

Which JUCE version are you using? Is the issue present on the develop branch?

Are you able to debug the issue on either of those platforms?

Pretty sure that’s intentional on Cubase’s part, so that VST3 plugins will load sessions saved with the VST2 version of the same plugin. Not sure why you’d want both installed at the same time. All our plugins VST3 plugins have this problem, and it hasn’t been an issue. Just don’t install both at the same time. :man_shrugging:

I’m on JUCE 8.0.6 master. Installed some older versions of my plugin built with JUCE 7.x, and I noticed that Cubase doesn’t show the VST2 version if VST3 is installed. So, I never discovered this before since I couldn’t load VST2 when VST3 was present.

I’ll need some time to debug this on other machines.

Of course, this isn’t a major issue since users can still use the VST3 version in Cubase. However, it’s not ideal that loading a VST2 instance causes the DAW to crash.

We are running into this same issue with our plugins built on JUCE 8.0.6. The issue is present in Cubase 13 and 14 running under Rosetta on Apple Silicon, and on Intel Macs. It is not present when running natively on Apple Silicon. I will check Windows ASAP (hopefully tomorrow).

There seem to be two separate things going wrong:

  • With JUCE_VST3_CAN_REPLACE_VST2 enabled and both VST2 and VST3 installed, the VST2 is showing up in Cubase (on JUCE 7 and earlier, only the VST3 would show - VST2 would be hidden)
  • The VST2 crashes in JuceVST3EditController::setComponentState()

The issue seems to have been introduced via the trio of commits mentioned/posted on this forum post. These are the 3 commits in question:

If I revert those 3 commits, then everything seemingly works as expected: only the VST3 shows in Cubase when both VST2 and VST3 are installed, and thus there’s no crashing VST2.

I can partially reproduce the issue using the GainPlugin demo: Both VST2 and VST3 appear (seemingly incorrect), but interestingly the VST2 loads fine (no crash). This happens on both v8.0.6 and on the latest tip of develop.
EDIT: I can reproduce the issue using the GainPlugin demo with JUCE_VST3_CAN_REPLACE_VST2=1 (and JUCE_FORCE_USE_LEGACY_PARAM_IDS=1 to get past this error), using v8.0.6 and the latest tip of develop.

Our end users may want to install both VST2 and VST3 for various reasons, so only installing one or the other is not an option. Given the bug seems to have started after the above changes, can the JUCE team please investigate and provide a fix? Thanks!

Another data point:

If I add back the old getUUIDForVST2ID() function from juce_PluginUtilities.h and update the VST2 wrapper’s handleVST3Compatibility() function to call it instead of VST3ClientExtensions::convertVST2PluginId(), then everything works as expected.

It seems like the logic of getUUIDForVST2ID() was perhaps not fully replicated in the new convertVST2PluginId() function?

EDIT:

I’ve been able to trace the problem with both VST3 and VST2 appearing to these lines of code. If you replace them with a standard memcpy, e.g. std::memcpy (args.ptr, uid.data(), uid.size());, then everything works as expected, so it appears convertVST2PluginId() is fine and it’s how it’s written to args.ptr that’s the problem. It looks like the String at line 1818 is being created as a char*, but the contents being copied in are unsigned char*?

With the change you’re suggesting does the VST3 still correctly replace the VST2 in a saved session? I’m guessing not as the change you’re suggesting doesn’t take into account that those lines aren’t copying the string, they are first converting the string of hex characters into byte values and then copying those byte values.

I suspect the reason this prevents the crash is that Cubase no longer detects that there is a compatible VST3 installed.

Could you maybe try debugging the plugin to see where it crashes?

From the looks of the crash report mentioned earlier in this thread, and from what you’ve said, it might be the crash is actually happening in the VST3. Maybe Cubase tries to load the VST3 when you select the VST2 but something is different?

Thanks for reporting this issue. A fix is now available on the develop branch:

Hi @reuk and @anthony-nicholls,

Thanks for the prompt replies and fix! I’ve confirmed this solves the issue for me. The VST3 correctly replaces the VST2 and reloads state and automation correctly.

I did try testing compatibility before the hotfix, and the VST3 was correctly replacing and recalling the VST2. The issue was only the VST2 was still showing up and crashing - and that’s now fixed.

Could you maybe try debugging the plugin to see where it crashes?

From the looks of the crash report mentioned earlier in this thread, and from what you’ve said, it might be the crash is actually happening in the VST3. Maybe Cubase tries to load the VST3 when you select the VST2 but something is different?

I think you are correct, in the debugger it was crashing in JuceVST3EditController::setComponentState() when it called audioProcessor->updateParameterMapping(); (as audioProcessor was null).

Thanks again!

1 Like