Diagnosing why you cannot create a stable subkey under a volatile parent key


A customer encountered crashes in their program's initialization code. They weren't able to reproduce the problem in-house, but their failure logs suggested it was coming from here:

var settingsKey =
    Registry.CurrentUser.CreateSubKey(
        "Software\\Contoso\\Common Settings\\Drawing Preferences");

The call was failing with System.IO.IO­Exception: Cannot create a stable subkey under a volatile parent key. The corresponding Win32 error code is ERROR_CHILD_MUST_BE_VOLATILE.

First of all, what does this error mean?

This error means exactly what is says: You cannot create a stable (non-volatile) subkey under a volatile parent key. All children of a volatile key must themselves be volatile.

Okay, but why is the parent key volatile?

We don't know for sure which key is the volatile parent, but it's one of Software, Software\\­Contoso, or Software\\­Contoso\\­Common Settings. We can probably rule out Software since that key is pre-created by the system. That leaves the other two Contoso keys. But they are intended to hold persistent settings. Why would anybody create those keys as volatile? That would defeat the purpose of the keys.

Ah, but perhaps the parent keys were created volatile by mistake. An often-overlooked detail of the Reg­Create­Key­Ex function (which is therefore also a detail of the Create­Sub­Key CLR method) is that if you ask for the key to be created as volatile, then the volatility applies to all keys created by the call. This means two things:

  • If the key already exists, then its stability is unchanged. If it was volatile before, then it remains volatile. If it was stable before, then it remains stable.
  • If the key doesn't already exist, then not only is the new key volatile, but the volatility also applies to any parent keys that didn't already exist.

By searching the code for any attempts to create volatile keys, we found this one that seemed suspicious:

var sessionSettings =
    Registry.CurrentUser.CreateSubKey(
        "Software\\Contoso\\Common Settings\\Current Session",
        RegistryOptions.Volatile);

The intent of this code was to create a volatile Current Session key to hold the user's temporary settings that should be discarded when the user logs off. However, if the Contoso\\Common Settings key doesn't yet exist, this will create not only a volatile Current Session, but also a volatile Common Settings key, and possibly even a volatile Contoso key!

My theory as to what is going on is that the failures are occurring on machines where the call to create the Current Session key (1) occurs when the Common Settings key does not already exist, (2) comes before the call to create the Drawing Preferences key, and (3) ends up being the call that creates the Common Settings key as a volatile key. One possibility is that this is the first time any program developed by Contoso has been run by this user, which means that none of the Contoso keys exist at the point the program starts. Another possibility is that the user, in a perhaps misguided attempt to fix a problem with a Contoso-developed program, deleted the entire Common Settings key, or possibly even the entire Contoso key.

The code to create the Current Session key should do so in two steps. First, create the stable parent key. Second, create the volatile subkey.

var commonSettings =
    Registry.CurrentUser.CreateSubKey(
        "Software\\Contoso\\Common Settings");
var sessionSettings = commonSettings.CreateSubKey(
        "Current Session",
        RegistryOptions.Volatile);

(Translating this to raw Win32 is left as an exercise for the reader.)

Comments (3)
  1. cheong00 says:

    This explains why the documentation of some application said when it fails some way, you need to delete the registry key for application then run the configure program again.

    Btw, is there any way support staffs can figure out a key is volatile or not? There seems no difference in RegEdit for HKLM\SYSTEM\CurrentControlSet on the display and the exported file. The “reg flags QUERY” command only works for subkey of HKLM\Software and yet it seems doesn’t say anything regarding volatility.

  2. The_Assimilator says:

    Raymond, consider using C# verbatim strings (the special character @) to make your registry strings less clunky to type, e.g.:

    var settingsKey =
    Registry.CurrentUser.CreateSubKey(
    @”Software\Contoso\Common Settings\Drawing Preferences”);

  3. ranta says:

    I read from NTDEV that RegCreateKeyEx in earlier versions of Windows would return ERROR_CHILD_MUST_BE_VOLATILE, but in Windows 2000 and XP, it would silently make the child key volatile. Now that I tried it on Windows 7 SP1 (both x64 and WOW64), it returned the error. Was it changed back in Windows Vista or 7, then?

Comments are closed.

Skip to main content