TL;DR
Two recent releases added parameters to the primary constructors of public classes:
- 1.22.0 added a 7th field to
Settings (autoInstrumentation).
- 1.25.0 added two trailing parameters to
EventPipeline (httpConfig, timeProvider).
In Kotlin, adding a parameter to a primary constructor — even with a default value — is a binary-incompatible change. The synthetic …$default(...) constructor that callers reference at the bytecode level disappears, and the new one has a different JVM descriptor.
Source-level callers that recompile against the new version are fine. Pre-built AARs/JARs (third-party SDKs that depend on analytics-kotlin and ship compiled artifacts to their customers) crash at app launch with NoSuchMethodError whenever the host application's Gradle graph resolves Segment to a version newer than the one those SDKs were compiled against.
Who is affected
- ❌ Third-party SDKs that wrap or extend
analytics-kotlin and publish a pre-built AAR/JAR — every consumer of those SDKs whose app resolves Segment ≥1.22.0 (for Settings) or ≥1.25.0 (for EventPipeline).
- ❌ End-user Android apps that include such an SDK alongside another transitive dependency that requests a newer Segment via
1.22.0+ or similar.
- ✅ Apps that depend on
analytics-kotlin directly and recompile against the new version — not affected; the Kotlin compiler simply emits bytecode against the new descriptor.
- ✅ Apps that hold Segment back to the version their SDKs were compiled against (e.g., via a strict pin or lockfile) — not affected, but at the cost of giving up newer Segment fixes.
The asymmetry is the key point: a Kotlin source-compatible change (default-valued parameter) is not binary-compatible. Downstream SDK vendors cannot fix this for their already-published artifacts — the bytecode is frozen.
Minimal repro:
- Build any small Android library that depends on
com.segment.analytics.kotlin:android:1.19.2 and constructs a Settings() (or any subset of its fields, leaving at least one defaulted).
- Publish it as an AAR (or just
assemble and consume the local artifact).
- In a separate consumer Android app, depend on that AAR and force-resolve
com.segment.analytics.kotlin:android to 1.25.0.
- Run the app → instant
NoSuchMethodError on the Settings constructor reference.
The same pattern with an EventPipeline(analytics, key, writeKey, flushPolicies, apiHost) call site reproduces the 1.25.0-specific break.
Where each break landed
| Break |
Class |
Commit |
First released in |
Added 7th field autoInstrumentation to primary ctor |
core/.../Settings.kt |
adeb09a (#279, "Add auto instrumentation settings") |
1.22.0 |
Added trailing httpConfig, timeProvider to primary ctor |
core/.../platform/EventPipeline.kt |
#300 ("Phase 4 — EventPipeline integration with smart retry system") |
1.25.0 |
TL;DR
Two recent releases added parameters to the primary constructors of public classes:
Settings(autoInstrumentation).EventPipeline(httpConfig,timeProvider).In Kotlin, adding a parameter to a primary constructor — even with a default value — is a binary-incompatible change. The synthetic
…$default(...)constructor that callers reference at the bytecode level disappears, and the new one has a different JVM descriptor.Source-level callers that recompile against the new version are fine. Pre-built AARs/JARs (third-party SDKs that depend on
analytics-kotlinand ship compiled artifacts to their customers) crash at app launch withNoSuchMethodErrorwhenever the host application's Gradle graph resolves Segment to a version newer than the one those SDKs were compiled against.Who is affected
analytics-kotlinand publish a pre-built AAR/JAR — every consumer of those SDKs whose app resolves Segment ≥1.22.0 (forSettings) or ≥1.25.0 (forEventPipeline).1.22.0+or similar.analytics-kotlindirectly and recompile against the new version — not affected; the Kotlin compiler simply emits bytecode against the new descriptor.The asymmetry is the key point: a Kotlin source-compatible change (default-valued parameter) is not binary-compatible. Downstream SDK vendors cannot fix this for their already-published artifacts — the bytecode is frozen.
Minimal repro:
com.segment.analytics.kotlin:android:1.19.2and constructs aSettings()(or any subset of its fields, leaving at least one defaulted).assembleand consume the local artifact).com.segment.analytics.kotlin:androidto1.25.0.NoSuchMethodErroron the Settings constructor reference.The same pattern with an
EventPipeline(analytics, key, writeKey, flushPolicies, apiHost)call site reproduces the 1.25.0-specific break.Where each break landed
autoInstrumentationto primary ctorcore/.../Settings.ktadeb09a(#279, "Add auto instrumentation settings")httpConfig,timeProviderto primary ctorcore/.../platform/EventPipeline.kt