# 2 Unremovable Geometry in Omniverse Scene – Can't Delete or Identify Source

I’m experiencing a strange issue in Omniverse where some geometry appears in my scene, but I can’t find where it’s coming from. Even when I turn off all the layers, the geometry remains visible.

The really odd part is that when I select it and try to delete it, I get a message saying “No prims selected”, even though I can clearly see the object. It’s almost like ghost geometry that doesn’t actually exist in the hierarchy.

I also had a look at the seperate files in USDview, just for debugging, but cut not find out…

Has anyone encountered this before? in the videos I demonstrate the issue in more detail, go through different tests and I actually managed to fix it (shown in the 3rd Video)

Any suggestions on how to track down the source or force other ways to fix this would be greatly appreciated!

P.s. the issue is probably related to my previous Topic Issues with Variants breaking due to Layers?




I fixed it, yet I would still like to know what was wrong with it…

I think this relates to your other post on LAYERS. Just like the first post, I think you are over focusing on Layers, rather than the Stage Tree. Use the Stage Tree for hiding and showing objects. Not the Layers. The layer system is much more complex. It is fine for loading it entire data sets on layers, and if you want to show/hide the entire layer, that also makes sense. But if you are trying to hide show more granular, specific objects, use the Stage Tree. You certainly do NOT want to go into a layer and start to mess around with the deltas. Those are very complex and are automatically set by the system. Not really designed for human use.

My advice is to reload and relearn the scene with a focus on a simple, single layer structure in root, and then do you work in the Stage Tree.

Hi Richard,
thx for the reply. But this particular issue was dealing with geometry that was there, but not there. My best guess now is that the cache from an ‘anomynos Layer’ was not erased correctly.

As I am digging into USD and the amazing workflows that can be achieved using layers (which make this format unique), I am going through the ‘USD Survival Guide’ and found some insights on Anonymous layers

Anonymous layers have these special features: (source: ‘USD Survival Guide’)

  • They are in-memory layers that have no real path or asset information fields.
  • We can additionally give a custom name suffix, so that we can identify the layer better visually
  • The identifier is not run through the asset resolver (Edit: I have to verify this again, but I’m fairly certain)
  • They cannot be saved via layer.Save(), it will return an error
  • We can convert them to “normal” layers, by assigning a non-anonymous identifier (layer.identifier="/file/path/myIdentifier.usd"), this also removes the save permission lock.

Here is how it might be solved in the future ( I have not testede it, it is an answer that I got from a prepromted DeepSeek R1, also being pointed at the ‘USD survival Guide’

Ah, this sounds like an issue with anonymous layers (temporary, in-memory layers) or composed overrides that are not visible. Here are steps to solve it:


1. Identify the “Ghost Prim”

Question: Where is the prim coming from?

  • Possibility 1: It is hidden in an anonymous layer (not saved to disk).
  • Possibility 2: It was loaded via a Reference/Payload that no longer exists.
  • Possibility 3: A composed override (e.g., in a Variant) is keeping it alive.

2. Solutions

A. Check All Anonymous Layers

Anonymous layers are not displayed in the layer list, but they exist in memory. Here’s how to find them:

from pxr import Sdf, Usd

# List all loaded layers (including anonymous ones)
all_layers = Sdf.Layer.GetLoadedLayers()

for layer in all_layers:
    if not layer.identifier:  # Anonymous layers have no file ID
        print("Anonymous layer found:", layer)
        # Search the layer for the prim
        for prim in layer.rootPrims:
            if prim.name == "NAME_OF_GHOST_PRIM":
                print("Prim found in anonymous layer:", prim.path)
                # Delete the prim
                layer.RemoveRootPrim(prim)

B. Clean Up the Stage

Sometimes prims “stick around” even after their layers are removed:

stage = omni.usd.get_context().get_stage()  # Omniverse

# Force a stage cleanup
stage.Reload()

C. Edit Low-Level Sdf Layers

If the prim is stuck in an anonymous layer that isn’t visible:

# Find all anonymous layers
anon_layers = [layer for layer in Sdf.Layer.GetLoadedLayers() if not layer.identifier]

# Delete the prim in all anonymous layers
target_prim_path = Sdf.Path("/Path/To/GhostPrim")
for layer in anon_layers:
    if layer.HasPrim(target_prim_path):
        layer.DeletePrim(target_prim_path)

D. Flatten the Stage (Nuclear Option)

Create a new stage without composition/overrides:

flattened_stage = stage.Flatten()
flattened_stage.Export("CleanedScene.usda")

3. Debugging Tools

usdview

  • Open the scene in usdview and use Layer Stack → Composition (Ctrl + L) to see where the prim is defined.

Inspect Layer Stack

stage = Usd.Stage.Open("scene.usda")

# Show all layers in the stack (including anonymous ones)
print(stage.GetLayerStack())

Mute Layers

Disable layers to find the culprit:

stage.MuteLayer(layer.identifier)  # Omniverse: omni.usd.get_context().mute_layer()

4. Common Causes

  • Overridden Payloads: A payload was loaded but not unloaded.
  • Instanced Prims: The prim is part of an instance (e.g., via UsdGeom.PointInstancer).
  • Undo History: Omniverse/Apps sometimes keep undo data in memory.

5. Workflow for Omniverse

  1. Reset the Stage:
omni.usd.get_context().new_stage()  # Clears all temporary layers
  1. Clear Undo History:
omni.kit.undo.get_undo_stack().clear()
  1. Clear Cache:
stage.ClearMetadata("customLayerData")  # Removes persistent data

Summary

  • Anonymous layers are often the cause – check them with Sdf.Layer.GetLoadedLayers().
  • Flattening the stage removes all overrides/composition.
  • In Omniverse: Use new_stage() or clear the undo stack.

p.s.

, the code snippets I provided are meant to be run in the Script Editor of your application (e.g., Omniverse, Blender, or any Python environment where USD is available). Here’s how to use them:

  • Omniverse: Open the Script Editor (Window → Script Editor) and paste the code.
  • Blender: Use the Scripting workspace and run the code in the text editor.
  • Standalone Python: Ensure you have the pxr module installed (pip install usd-core) and run the code in a Python environment.
1 Like

Ok. Good info. But again, much more simply to start the project over and not use layers. Or use layers in a less complex way. And just because you read something on USD in general, does not mean it works in Omniverse. USD as a format was invented by Pixar. You might be reading about layer technology that only works with Pixar’s version of USD in Renderman. Not in our version in Omniverse.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.