dotnet/wpf · error · DirectoryNotFoundException

SR.CanNotOnNonExistStorage

Error message

SR.CanNotOnNonExistStorage

What it means

StorageInfo.VerifyExists checks InternalExists and throws DirectoryNotFoundException with SR.CanNotOnNonExistStorage when the storage does not exist in the compound file. Most public StorageInfo members call VerifyExists first, so operating on a deleted or never-created sub-storage fails fast with a directory-not-found semantics.

Solutions

  1. Check the Exists property on the StorageInfo before calling its methods.
  2. Re-fetch a fresh StorageInfo from the root after any delete/rename instead of reusing stale references.
  3. Create the storage first (CreateSubStorage) if it is supposed to exist.
  4. Catch DirectoryNotFoundException around storage operations to treat missing storages as empty.

Example fix

// before
var child = root.GetStorageInfo("Part1");
child.DeleteSubStorage("Inner"); // DirectoryNotFoundException if Part1 deleted
// after
var child = root.GetStorageInfo("Part1");
if (child.Exists)
    child.DeleteSubStorage("Inner");
Defensive patterns

Strategy: validation

Validate before calling

if (storageInfo == null || !storageInfo.Exists)
    return null; // or recreate: root.CreateSubStorage(name)

Prevention

When it happens

Trigger: Holding a StorageInfo reference and calling Exists-sensitive members (CreateSubStorage, CreateStreamInfo, enumerators, Open) after the sub-storage was deleted via DeleteSubStorage, or constructing/accessing a name that was never created.

Common situations: Stale StorageInfo references cached across container edits; misspelled storage names; deleting a storage then trying to enumerate its children.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/41e926246354d4c1. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/System/IO/Packaging/CompoundFile/StorageInfo.cs:1114

                    SR.Format(SR.NamedAPIFailure, "IStorage::OpenStorage"), 
                    nativeCallErrorCode ));
        }
        // STG_E_NOTFOUND - return openSuccess as false 

        return openSuccess;
    }

    /// <summary>
    /// Most of the time internal methods that want to do an internal check 
    /// to see if a storage exists is only interested in proceeding if it does.
    /// If it doesn't, abort with an exception.  This implements the little
    /// shortcut.
    /// </summary>
    private void VerifyExists()
    {
        if( !InternalExists() )
        {
            throw new DirectoryNotFoundException(
                SR.CanNotOnNonExistStorage);
        }
        return;
    }

    /// <summary>
    /// Grabs the STATSTG representing us
    /// </summary>
    private System.Runtime.InteropServices.ComTypes.STATSTG GetStat()
    {
        System.Runtime.InteropServices.ComTypes.STATSTG returnValue;

        VerifyExists();

        core.safeIStorage.Stat( out returnValue, 0 );

        return returnValue;
    }

View on GitHub (pinned to 81131a70a4)