Skip to content

Secondary bidder: NPE while merging bid rejection trackers #4686

Closed

Description

@zxPhoenix

Environment:

  • PBS version: 4.0.0.0
  • EU (TCF)

Description:
I got new NPE in logs. Auctions coverage is not too big but it worth to address this issue.

The issue is a mismatch between the bidder keys in the rejection tracker map and the bidder keys in the auction participation map.

ExchangeService.mergeBidRejectionTrackers iterates every tracker key, then looks up a future response with that bidder name. If no matching participation exists, the lookup returns null. The merge helper then tries to preserve the old tracker—but that lookup can also return null. That null reaches Collectors.toMap, which throws the reported NullPointerException because it does not allow null values.

So the immediate cause is a missing matching response combined with a missing old tracker for a key being merged.

The stacktace:

java.lang.NullPointerException
    at java.base/java.util.Objects.requireNonNull(Objects.java:220)
    at java.base/java.util.stream.Collectors.lambda$uniqKeysMapAccumulator$0(Collectors.java:180)
    at java.base/java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)
    at java.base/java.util.TreeMap$KeySpliterator.forEachRemaining(TreeMap.java:3107)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:570)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:560)
    at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:265)
    at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:723)
    at org.prebid.server.auction.ExchangeService.mergeBidRejectionTrackers(ExchangeService.java:1474)
    at org.prebid.server.auction.ExchangeService.lambda$processAndRequestBids$1(ExchangeService.java:1225)
    at io.vertx.core.impl.future.Transformation.complete(Transformation.java:39)
    at io.vertx.core.impl.future.FutureBase.emitResult(FutureBase.java:68)
    at io.vertx.core.impl.future.FutureImpl.completeInternal(FutureImpl.java:163)
    at io.vertx.core.impl.future.FutureImpl.tryComplete(FutureImpl.java:169)
    at io.vertx.core.impl.future.CompositeFutureImpl.doComplete(CompositeFutureImpl.java:218)
    at io.vertx.core.impl.future.CompositeFutureImpl.onSuccess(CompositeFutureImpl.java:123)
    at io.vertx.core.impl.future.CompositeFutureImpl.complete(CompositeFutureImpl.java:85)
    at io.vertx.core.impl.future.FutureBase.emitResult(FutureBase.java:68)
    at io.vertx.core.impl.future.FutureImpl.completeInternal(FutureImpl.java:163)
    at io.vertx.core.impl.future.FutureBase.emitResult(FutureBase.java:68)
    at io.vertx.core.impl.future.SucceededFuture.addListener(SucceededFuture.java:89)
    at io.vertx.core.impl.future.Composition.complete(Composition.java:48)
    at io.vertx.core.impl.future.FutureBase.emitResult(FutureBase.java:68)
    at io.vertx.core.impl.future.FutureImpl.completeInternal(FutureImpl.java:163)
    at io.vertx.core.impl.future.FutureBase.emitResult(FutureBase.java:68)
    at io.vertx.core.impl.future.FutureImpl.completeInternal(FutureImpl.java:163)
    at io.vertx.core.impl.future.Mapping.complete(Mapping.java:45)
    at io.vertx.core.impl.future.FutureBase.emitResult(FutureBase.java:68)
    at io.vertx.core.impl.future.FutureImpl.completeInternal(FutureImpl.java:163)
    at io.vertx.core.impl.future.FutureBase.emitResult(FutureBase.java:68)
    at io.vertx.core.impl.future.FutureImpl.addListener(FutureImpl.java:135)
    at io.vertx.core.impl.future.Composition.complete(Composition.java:48)
    at io.vertx.core.impl.future.FutureBase.emitResult(FutureBase.java:68)
    at io.vertx.core.impl.future.FutureImpl.completeInternal(FutureImpl.java:163)
    at io.vertx.core.impl.future.FutureBase.emitResult(FutureBase.java:68)
    at io.vertx.core.impl.future.FutureImpl.completeInternal(FutureImpl.java:163)
    at io.vertx.core.impl.future.Mapping.complete(Mapping.java:45)
    at io.vertx.core.impl.future.FutureBase.emitResult(FutureBase.java:68)
    at io.vertx.core.impl.future.FutureImpl.completeInternal(FutureImpl.java:163)
    at io.vertx.core.impl.future.Mapping.complete(Mapping.java:45)
    at io.vertx.core.impl.future.FutureBase.emitResult(FutureBase.java:68)
    at io.vertx.core.impl.future.FutureImpl.completeInternal(FutureImpl.java:163)
    at io.vertx.core.impl.future.FutureImpl$ListenerArray.complete(FutureImpl.java:214)
    at io.vertx.core.impl.future.FutureBase.emitResult(FutureBase.java:68)
    at io.vertx.core.impl.future.FutureImpl.completeInternal(FutureImpl.java:163)
    at io.vertx.core.impl.future.Mapping.complete(Mapping.java:45)
    at io.vertx.core.impl.future.FutureBase.emitResult(FutureBase.java:68)
    at io.vertx.core.impl.future.FutureImpl.completeInternal(FutureImpl.java:163)
    at io.vertx.core.impl.future.FutureImpl.tryComplete(FutureImpl.java:169)
    at io.vertx.core.impl.future.CompositeFutureImpl.doComplete(CompositeFutureImpl.java:218)
    at io.vertx.core.impl.future.CompositeFutureImpl.onSuccess(CompositeFutureImpl.java:123)
    at io.vertx.core.impl.future.CompositeFutureImpl.complete(CompositeFutureImpl.java:85)
    at io.vertx.core.impl.future.FutureBase.emitResult(FutureBase.java:68)
    at io.vertx.core.impl.future.FutureImpl.completeInternal(FutureImpl.java:163)
    at io.vertx.core.impl.future.FutureImpl.tryComplete(FutureImpl.java:169)
    at io.vertx.core.impl.future.CompositeFutureImpl.doComplete(CompositeFutureImpl.java:218)
    at io.vertx.core.impl.future.CompositeFutureImpl.onSuccess(CompositeFutureImpl.java:123)
    at io.vertx.core.impl.future.CompositeFutureImpl.complete(CompositeFutureImpl.java:85)
    at io.vertx.core.impl.future.FutureBase.emitResult(FutureBase.java:68)
    at io.vertx.core.impl.future.FutureImpl.completeInternal(FutureImpl.java:163)
    at io.vertx.core.impl.future.Mapping.complete(Mapping.java:45)
    at io.vertx.core.impl.future.FutureBase.emitResult(FutureBase.java:68)
    at io.vertx.core.impl.future.FutureImpl.completeInternal(FutureImpl.java:163)
    at io.vertx.core.impl.future.Mapping.complete(Mapping.java:45)
    at io.vertx.core.impl.future.FutureBase.emitResult(FutureBase.java:68)
    at io.vertx.core.impl.future.FutureImpl.completeInternal(FutureImpl.java:163)
    at io.vertx.core.impl.future.FutureBase.emitResult(FutureBase.java:68)
    at io.vertx.core.impl.future.SucceededFuture.addListener(SucceededFuture.java:89)
    at io.vertx.core.impl.future.Composition.complete(Composition.java:48)
    at io.vertx.core.impl.future.FutureBase.emitResult(FutureBase.java:68)
    at io.vertx.core.impl.future.FutureImpl.completeInternal(FutureImpl.java:163)
    at io.vertx.core.impl.future.FutureBase.emitResult(FutureBase.java:68)
    at io.vertx.core.impl.future.SucceededFuture.addListener(SucceededFuture.java:89)
    at io.vertx.core.impl.future.Composition.complete(Composition.java:48)
    at io.vertx.core.impl.future.FutureBase.emitResult(FutureBase.java:68)
    at io.vertx.core.impl.future.FutureImpl.completeInternal(FutureImpl.java:163)
    at io.vertx.core.impl.future.FutureBase.emitResult(FutureBase.java:68)
    at io.vertx.core.impl.future.SucceededFuture.addListener(SucceededFuture.java:89)
    at io.vertx.core.impl.future.Composition.complete(Composition.java:48)
    at io.vertx.core.impl.future.FutureBase.emitResult(FutureBase.java:68)
    at io.vertx.core.impl.future.FutureImpl.completeInternal(FutureImpl.java:163)
    at io.vertx.core.impl.future.FutureImpl.tryComplete(FutureImpl.java:169)
    at io.vertx.core.Promise.complete(Promise.java:76)
    at io.vertx.core.Promise.handle(Promise.java:52)
    at io.vertx.circuitbreaker.impl.CircuitBreakerImpl$Completion.lambda$handle$0(CircuitBreakerImpl.java:535)

Activity

  1. zxPhoenix commented on Oct 29, 2026

    @zxPhoenix
    ContributorAuthor

    I traced the NPE to our customization, which adds a tracker entry for a bidder who isn’t in the auction. I couldn’t reproduce the issue with standard Prebid Server Java, so I’ve closed the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions