AEM 6.5 to 6.5 LTS Migration: What Actually Breaks in Custom Code

By Alberto Zarza Martín · · 6 min read

AEM 6.5 LTS is not a feature upgrade — it is a runtime upgrade wearing a familiar version number. Most of the pain in a migration comes from custom code that quietly depended on internals that LTS removes or replaces. Here is what breaks most often in practice.

1. Deprecated and removed APIs

Several APIs that were merely deprecated in 6.5.x are fully removed in LTS. The usual suspects are old Granite UI dialog APIs, legacy Workflow APIs, and some Sling Commons utilities that got replaced by their Jakarta or updated equivalents. A bundle that compiled cleanly against 6.5.23 can fail to resolve entirely against LTS because an imported package no longer exists.

2. Guava version conflicts

LTS ships a different Guava baseline, and if your bundles embed their own Guava version instead of consuming the platform's, you will see NoSuchMethodError or ClassNotFoundException at runtime rather than at build time — which makes this one of the more frustrating failures to trace back to its root cause.

3. Uber JAR repointing

Every project pom that pins the AEM Uber JAR (or the SDK equivalent) needs repointing to the LTS artifact. Skipping this means your build compiles against the wrong API surface and passes locally while failing on the LTS instance.

4. Java version mismatch

LTS requires Java 17 as the baseline runtime. Bundles compiled with older bytecode targets are compatible, but reflection-heavy code, custom class loaders, and any library depending on `sun.*` internal packages tend to break under the stricter module system. This deserves its own migration pass — see the companion article on Java 17 migration for bundles.

Recommended remediation order

Treat this as a dependency and API-surface audit before it becomes a functional testing problem — it is far cheaper to catch a removed API at compile time than to chase a runtime stack trace three environments later.