Product Structure Explorer hangs when traversing deep BOM hierarchies with 15+ levels

Hi all,

We’re running Windchill 11.2 M030 and experiencing a consistent hang in Product Structure Explorer (PSE) when trying to expand or traverse BOM hierarchies that go beyond 15 levels deep. The UI becomes completely unresponsive after roughly 30-45 seconds, and eventually we get a browser timeout or the Windchill session just dies.

The affected assemblies are top-level vehicle platform structures with around 18-22 levels of nesting and approximately 12,000–15,000 total component nodes. PSE loads the first few levels fine, but once we try to expand past level 12-13, the spinning wheel appears and never recovers.

We checked the method server logs and see repeated entries like:

WARN com.ptc.windchill.structmgr.PartList - PartList traversal exceeded threshold: 12000 nodes, iteration depth: 16 ERROR wt.pom.QueryProcessor - Query timeout after 30000ms on PartUsageLink fetch

We’ve already tried:

  • Increasing JVM heap on the method server to 8GB
  • Setting wt.pom.queryTimeout=60000 in wt.properties
  • Disabling “Load All” on PSE startup

None of these helped. Our DBA confirmed the Oracle queries themselves are completing in under 2 seconds, so it doesn’t appear to be a DB bottleneck. Is there a PSE-specific configuration or a known Windchill defect related to deep BOM traversal in 11.2 M030?

Any guidance appreciated.

I’ve dealt with this exact class of problem on two separate 11.2 M030 deployments. Here’s a comprehensive breakdown of what’s happening and how to resolve it:

Root Cause: Windchill PSE uses a recursive StructureWalker internally that fetches WTPartUsageLink objects level-by-level. In 11.2 M030, there’s a regression (introduced around M025) where the StructureContext object accumulates references to fetched nodes in a non-paginated in-memory list. Once the list exceeds approximately 10,000–12,000 entries (which happens fast on 18+ level assemblies), two problems compound:

  1. Serialization of the context object to pass back to the web tier becomes extremely expensive (~2–4 seconds per level).
  2. A pessimistic read lock on WTPartUsageLink is held for the entire traversal duration, causing subsequent expand requests to queue on the same lock — producing exactly the thread dump pattern you observed.

Immediate Workaround (no restart required for properties loaded dynamically):

Add or update the following in <WT_HOME>/codebase/WEB-INF/conf/wt.properties:

# Increase structure depth ceiling
wt.pds.maxStructureDepth=30

# Reduce page size to prevent in-memory list bloat
wt.pds.structurePageSize=300

# Disable fine-grained locking to break the deadlock pattern
wt.pds.enableLazyLoadLocking=false

# Extend query timeout to give Oracle more room on complex queries
wt.pom.queryTimeout=90000

# Tune the StructureContext cache expiry (default is 600s, reduce to free memory faster)
wt.pds.contextCacheTTL=180

After editing, restart the Windchill method server:

$ cd <WT_HOME>/bin
$ windchill stop
$ windchill start

PSE-Specific Configuration (xconf): You should also review the PSE-specific XCONF properties. Run:

$ windchill wt.load.LoadFileSet -file <WT_HOME>/codebase/config/properties/PSEConfig.xconf

Inside PSEConfig.xconf, look for <Property name="pse.maxExpansionNodes"> and increase it from the default 10000 to 20000 or higher depending on your largest assembly size.

Longer-Term Fix: PTC has confirmed a patch for SPR #CS0312847 is included in 11.2 M040. I’d strongly recommend planning an upgrade to M040 or requesting the specific hotfix from PTC support for M030. Reference the SPR when opening your support case — PTC will typically provide a targeted patch JAR (windchill-structmgr-patch-CS0312847.jar) that you drop into <WT_HOME>/codebase/WEB-INF/lib/ and restart.

Validation: After applying the property changes, test with your largest assembly and monitor the method server thread dump. You should see threads in getLinks() clear within a few seconds rather than accumulating. Also watch your method server heap — with structurePageSize=300, memory pressure during traversal should drop noticeably.

Hope this gets you unstuck. Let me know if the SPR patch resolves it completely after you open the support case.


This draft is based on general Windchill knowledge. It has not been verified against your specific version and environment. Practitioners: verify the steps and share your experience below.

We’ve seen similar behavior in our environment on 11.2 M020. One thing worth checking is the wt.pds.maxStructureDepth property in your wt.properties file. By default it’s set to 15 in some builds, and once the traversal hits that ceiling, PSE can stall rather than gracefully paginate. Try bumping it to 25 or 30 and see if that at least changes the failure point. Also make sure you’re not hitting the default Windchill RMI timeout during the recursive fetches.

The PartUsageLink fetch timeout in your logs is a red flag. Even if the DB query finishes fast, Windchill’s StructureContext caching layer can serialize results in a way that blocks the method server thread pool. Check your com.ptc.windchill.structmgr thread pool size in MethodServer.properties. If all threads are consumed by a single deep traversal, new requests queue up and the session appears hung. What’s your current maxMethodServerThreads setting?

Thanks both — useful directions. @windchill_admin_tbauer: I checked and wt.pds.maxStructureDepth isn’t explicitly set in our wt.properties, so it’s likely using the default. I’ll try setting it to 25.

@struct_mgr_lpetrova: Our maxMethodServerThreads is currently 100. During the hang, I pulled a thread dump and saw around 40 threads all stuck in wt.pom.PersistenceManagerSvr.getLinks() with identical stack traces for the same assembly OID. Could that be the StructureContext serialization issue you mentioned? Is there a specific property to control that caching behavior?

That thread dump pattern — multiple threads piled up in PersistenceManagerSvr.getLinks() for the same OID — strongly suggests a lock contention issue in the WTPartUsageLink cache. There’s a known issue in 11.2 M030 (PTC SPR #CS0312847) where PSE’s lazy-load mechanism doesn’t properly release read locks on PartUsageLink objects when depth exceeds the internal pagination boundary (~12 levels). You should open a case with PTC Support and reference that SPR. In the meantime, try setting wt.pds.structurePageSize=500 and wt.pds.enableLazyLoadLocking=false in wt.properties as a temporary workaround. The latter disables fine-grained locking but may relieve the contention.