fix(deps): pin opentelemetry-bom to 1.61.0 to fix staging startup crash #596
Reference in New Issue
Block a user
Delete Branch "feat/issue-580-sentry-backend"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
The first staging nightly after #595 merged failed with
NoSuchMethodError: GlobalOpenTelemetry.getOrNoop()— the backend crashed before it could start.Root cause:
opentelemetry-spring-boot-starter:2.27.0was built againstopentelemetry-api:1.61.0, but Spring Boot 4.0.0's BOM only manages1.55.0. The methodgetOrNoop()was added between those two versions.Fix: add a
<dependencyManagement>import ofopentelemetry-bom:1.61.0tobackend/pom.xml. This overrides the Spring Boot BOM's version before it applies, so all core OTel artifacts resolve to the version the instrumentation starter actually requires.1603 backend tests pass. Build compiles cleanly.
Test plan
NoSuchMethodErroron startup)🤖 Generated with Claude Code
🏛️ Markus Keller (@mkeller) — Application Architect
Verdict: ✅ Approved
What I checked
Single
pom.xmlchange importingopentelemetry-bom:1.61.0into<dependencyManagement>. No new packages, routes, Flyway migrations, Docker services, or external system integrations — no documentation updates are required.Findings
The fix is correct and well-documented. Importing the OTel BOM before the Spring Boot BOM applies is the canonical Maven way to override a managed version. The in-XML comment explains the exact threat model (which starter version, which API version, which missing method). This is exactly the level of explanation a future maintainer needs to avoid reverting it "to simplify".
One concern worth verifying — BOM override breadth. Importing
opentelemetry-bom:1.61.0as a BOM import overrides the managed version for all core OTel artifacts, not justopentelemetry-api. Most of the time this is fine (the BOM is internally consistent), but it's worth running:...and confirming that no Spring Boot-managed OTel bridge artifact (e.g.
opentelemetry-spring-boot-autoconfigure) is now resolving at a version the autoconfigure module doesn't expect. If all 1603 tests pass including the Spring context startup tests, this concern is already answered in practice.No ADR needed. Pinning a transitive BOM version to resolve a known starter/API version mismatch is a maintenance action, not an architectural decision with lasting structural consequences.
Summary
Minimal, targeted, well-explained. The existing test suite passing is sufficient validation for this class of fix.
👨💻 Felix Brandt (@felixbrandt) — Senior Fullstack Developer
Verdict: ✅ Approved
What I checked
Clean code, comment quality, TDD evidence, and whether the fix is the minimum necessary change.
Findings
Code quality: clean. The XML is minimal — exactly 14 lines, no redundancy, no unnecessary structure. The comment inside
pom.xmlcorrectly explains the why (which versions, which method was missing, which order Maven BOMs apply). This is one of the rare cases where a comment earns its place.TDD: not applicable here. A
NoSuchMethodErrorduring JVM classloading is not testable at the JUnit/Mockito unit level — the method resolution happens before any test code can assert on it. The 1603 existing tests passing (including, presumably, any@SpringBootTestintegration tests that boot the actual Spring context) are the correct red/green evidence for this class of bug. I won't flag absence of a unit test as a blocker.Suggestion (non-blocking): If there's a
ApplicationContextTestor any@SpringBootTestthat loads the full context without a mocked embedded server, that test is implicitly testing this fix. It might be worth a one-line comment in that test's class-level Javadoc to note it catches startup classpath issues. Not a blocker — just a way to make the intent explicit for future readers.PR description: Excellent. Root cause, fix rationale, and validation steps are all present. This is the kind of description that makes archaeology unnecessary six months from now.
🚀 Tobias Wendt (@tobiwendt) — DevOps & Platform Engineer
Verdict: ✅ Approved
What I checked
Dependency pinning strategy, reproducibility, CI validation, and Renovate coverage.
Findings
The fix is the right approach. Pinning the OTel BOM to an explicit version in
<dependencyManagement>is exactly what you want — reproducible, auditable, reviewable. No magic ranges, no SNAPSHOT references. The in-XML comment makes the version lock visible and justified to anyone runningmvn dependency:treeor reviewing future Renovate PRs.Blocker: Renovate coverage. If
io.opentelemetry:opentelemetry-bomis not in Renovate's watched scope, this pin will silently drift. Whenopentelemetry-spring-boot-starteris upgraded again in the future,1.61.0may become stale — and we'll hit the same startup crash again in six months. Check yourrenovate.json:Maven BOM imports in
<dependencyManagement>are not always auto-detected by Renovate depending on configuration. Worth confirming the bot will pick this up.CI gate is correct. 1603 backend tests + CI green is the right validation signal. The "next staging nightly" test plan item is the real-world smoke test.
No infrastructure changes. No Compose file, Caddyfile, or CI workflow touched — nothing operationally changes.
📋 Elicit — Requirements Engineer
Verdict: ✅ Approved
What I checked
Requirements traceability, test plan completeness, and NFR coverage.
Findings
NFR addressed: Availability / Reliability. This PR directly addresses a critical non-functional requirement failure:
NFR-AVAIL: the backend shall start successfully and serve requests. ANoSuchMethodErrorat JVM startup is a complete service outage — the highest severity NFR failure class.Requirements traceability is clear. The PR description traces:
<dependencyManagement>This is a well-formed fix description. No ambiguity about scope, cause, or resolution.
Test plan observation (non-blocking). The second test plan item — "Next staging nightly: backend starts successfully" — is a manually verified, time-delayed acceptance criterion. This is acceptable for a hotfix, but it would be worth considering whether a startup smoke test (e.g. a CI step that hits
/actuator/healthagainst the built JAR before deployment) could turn this into an automatically verifiable gate on every future PR, rather than only verified at nightly deployment time.No feature requirements affected. This is a pure infrastructure fix. No user-facing behavior changes.
🔐 Nora "NullX" Steiner — Application Security Engineer
Verdict: ✅ Approved
What I checked
Supply chain trust, version pinning strategy, and any indirect security implications of the dependency change.
Findings
Supply chain: trusted artifact.
io.opentelemetry:opentelemetry-bomis published by the CNCF OpenTelemetry project — a well-known, widely-audited, industry-standard observability framework. Version1.61.0is a stable release. No concern here.Explicit version pin is better for security than a range. A hardcoded
<version>1.61.0</version>means Renovate (or a human) must explicitly review and approve any version bump. A range like[1.61.0,)could silently pull in a future release that hasn't been reviewed. The current approach is the correct one from a supply chain hardening perspective.No attack surface changes. This PR does not:
The only effect is that OTel core artifacts resolve at
1.61.0instead of1.55.0. No known CVEs in either version that are relevant to this application's attack surface.OWASP Dependency-Check note (informational). If the project runs OWASP Dependency-Check in CI, the check will now verify
1.61.0instead of1.55.0. If it wasn't running before, this PR would be a good moment to add it — but that's a separate task, not a blocker for this fix.🧪 Sara Holt (@saraholt) — QA Engineer & Test Strategist
Verdict: ✅ Approved
What I checked
Test coverage, regression risk, and whether the fix is verifiable by the existing test suite.
Findings
1603 tests passing is the right signal — but only if the Spring context boots. A
NoSuchMethodError: GlobalOpenTelemetry.getOrNoop()fails at JVM classloading, before any business logic runs. This class of bug is only caught by tests that actually boot the SpringApplicationContext— i.e.@SpringBootTestintegration tests. JUnit unit tests with@ExtendWith(MockitoExtension.class)would pass even with the broken version, because they never start the context.Verification question (non-blocking): Does the test suite include at least one
@SpringBootTestthat boots the full context (even just for migration testing via Testcontainers)? If yes, that test was the implicit red before this fix and is now the regression guard. If the suite is exclusively@WebMvcTestslices and@ExtendWith(MockitoExtension.class)unit tests, the existing suite would not have caught this — and won't catch a regression.Given that the PR description says "1603 backend tests pass", I'll assume there are integration tests that boot the context. But it's worth confirming.
Suggestion (non-blocking): If there's an
ApplicationContextTestorMigrationIntegrationTestthat loads the full Spring context, add a brief comment or test name note that it serves as a startup health check. This makes the regression guard visible to the next reviewer rather than implicit.Test plan is appropriate. CI green + staging nightly is the correct two-gate validation for an infra dependency fix. No behavioral changes, so no behavioral test cases are needed.
🎨 Leonie Voss (@leonievoss) — UI/UX Designer & Accessibility Strategist
Verdict: ✅ Approved
What I checked
Any frontend, UI, or accessibility implications of this change.
Findings
This PR modifies a single backend Maven configuration file (
backend/pom.xml) to fix a startup crash caused by a dependency version mismatch. There are no frontend changes, no Svelte components, no new routes, no visual changes, no accessibility implications, and no impact on the user experience.LGTM from a UI/UX perspective — the fix restores service availability, which is the prerequisite for any UI to function at all.