fix(sdk-logs): avoid null _currentExport access in _flushAll#6763
Merged
pichlermarc merged 1 commit intoJun 3, 2026
Merged
Conversation
|
|
Captures `this._currentExport` into a local before the awaits inside
`_flushAll`. The previous code dereferenced `this._currentExport` after
`await this._exporter.forceFlush()`, but the in-flight export may have
completed during that await and `_exportOneBatch`'s completion handler
nullifies `this._currentExport`, causing:
TypeError: Cannot read properties of null (reading 'exportCompleted')
In browsers this surfaces as an unhandled rejection because the
auto-flush listeners installed by the browser `BatchLogRecordProcessor`
invoke `void this.forceFlush()` on `visibilitychange` and `pagehide`.
Adds a unit test reproducing the race.
Signed-off-by: Janealter <24541204+Janealter@users.noreply.github.com>
Janealter
force-pushed
the
fix/sdk-logs-flushAll-race
branch
from
May 26, 2026 16:46
cde1101 to
6759b88
Compare
pichlermarc
approved these changes
Jun 3, 2026
pichlermarc
left a comment
Member
There was a problem hiding this comment.
good catch!
thank you for fixing this. 🙌
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #6763 +/- ##
=======================================
Coverage 94.92% 94.92%
=======================================
Files 377 377
Lines 12818 12819 +1
Branches 2924 2924
=======================================
+ Hits 12168 12169 +1
Misses 650 650
🚀 New features to boost your workflow:
|
Contributor
|
Thank you for your contribution @Janealter! 🎉 We would like to hear from you about your experience contributing to OpenTelemetry by taking a few minutes to fill out this survey. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Which problem is this PR solving?
BatchLogRecordProcessor._flushAllcan throwTypeError: Cannot read properties of null (reading 'exportCompleted')when aforceFlush()callraces against the natural completion of a background export.
Reproduction
scheduled-delay timer or because a batch filled up).
_exportOneBatchset
this._currentExport = exportOpand attachedexportOp.exportCompleted.then(() => { this._currentExport = null; … })as a fire-and-forget completion handler.
forceFlush()is called and enters_flushAll(). The checkif (this._currentExport !== null)passes, and the code awaitsthis._exporter.forceFlush()..thenhandler above runs, settingthis._currentExport = null._flushAll()resumes and evaluatesawait this._currentExport.exportCompleted.this._currentExportis nownull, throwingTypeError.In browsers this surfaces as an unhandled rejection because the browser
BatchLogRecordProcessorregistersvisibilitychange/pagehidelistenersthat call
void this.forceFlush()(no.catch()attached). Userstab-switching during normal usage trigger the race very frequently in
production.
The same race is reachable from
_shutdown()(which also calls_flushAll()).Affected versions
Introduced by #6356 (
feat(sdk-logs)!: invoke exporter forceFlush without first awaiting export), shipped in@opentelemetry/sdk-logs@0.215.0. Thesame code path is unchanged on
main(verified against0.215.0through0.218.0and HEAD).Short description of the changes
this._currentExportinto a localinFlightconst before theawaits, then dereference the local. The trailing
this._currentExport = nullis kept so the field still reflects "noin-flight" once the wait is done (idempotent if the completion handler
already nulled it).
test/common/export/BatchLogRecordProcessor.test.ts(
should not throw when in-flight export completes between awaits in _flushAll) that deterministically reproduces the race using a customexporter with controllable
exportandforceFlushresolutions.Without the fix, the new test fails with
TypeError: Cannot read properties of null (reading 'exportCompleted')at the exact line affected.
Type of change
How Has This Been Tested?
forceFlush()call with the completion of a background export. Test fails on
mainwith the exact upstream error, passes with the fix.
@opentelemetry/sdk-logscommon tests still pass(
nx run @opentelemetry/sdk-logs:test— 198 passing).nx run @opentelemetry/sdk-logs:lintpasses.Checklist:
experimental/CHANGELOG.md→ Unreleased →Bug Fixes