pinpoint-apm/pinpoint · warning

Invalid from UserNode:{}

Error message

Invalid from UserNode:{}

What it means

Also in DefaultNodeHistogramFactory.createUserNodeHistogram: when findFromLink returns more than one incoming link for the User node, the factory logs 'Invalid from UserNode' with the whole link list. The code deliberately continues, using the first link (index 0) as the source for the histogram, so the resulting histogram may reflect an arbitrary one of several user links.

Source

Thrown at web/src/main/java/com/navercorp/pinpoint/web/applicationmap/appender/histogram/DefaultNodeHistogramFactory.java:119

            AgentTimeHistogramBuilder agentTimeBuilder = new AgentTimeHistogramBuilder(terminalApplication, range);
            AgentTimeHistogram agentTimeHistogram = agentTimeBuilder.buildTarget(mergeSource);
            nodeBuilder.setAgentTimeHistogram(agentTimeHistogram);
        }

        return nodeBuilder.build();
    }

    @Override
    public NodeHistogram createUserNodeHistogram(Application userApplication, Range range, LinkList linkList) {
        // for User nodes, find its source link and create the histogram
        final List<Link> fromLink = linkList.findFromLink(userApplication);
        if (fromLink.isEmpty()) {
            logger.warn("from UserNode not found:{}", userApplication);
            return createEmptyNodeHistogram(userApplication, range);
        } else if (fromLink.size() > 1) {
            // log and use first(0) link.
            logger.warn("Invalid from UserNode:{}", linkList.getLinkList());
        }
        final Link sourceLink = fromLink.get(0);

        final NodeHistogram.Builder builder = NodeHistogram.newBuilder(userApplication, range);
        builder.setApplicationHistogram(sourceLink.getHistogram());

        ApplicationTimeHistogram histogramData = sourceLink.getTargetApplicationTimeSeriesHistogramData();
        builder.setApplicationTimeHistogram(histogramData);
        return builder.build();
    }

    @Override
    public NodeHistogram createQueueNodeHistogram(Application queueApplication, Range range, LinkList linkList) {
        final List<Link> toLinkList = linkList.findToLink(queueApplication);
        if (toLinkList.isEmpty()) {
            return NodeHistogram.empty(queueApplication, range);
        }

View on GitHub (pinned to 744c3d3075)

Solutions

  1. Deduplicate USER->APP links when building/merging the LinkList so each user application has exactly one from-link.
  2. Check the link-merging code path (LinkList/MapLinks) for conditions that append duplicate user links.
  3. Log/inspect linkList contents shown in the warning to identify which builder produced the extra link.
  4. If determinism matters, explicitly select the desired source link rather than relying on get(0).

Example fix

// before
final Link sourceLink = fromLink.get(0);
// after
final Link sourceLink = fromLink.stream()
        .min(Comparator.comparing(Link::getLinkKey))
        .orElseThrow(() -> new IllegalStateException("no user link for " + userApplication));
Defensive patterns

Strategy: validation

Validate before calling

// ensure exactly one from-link exists before calling the factory
List<Link> fromLinks = linkList.findFromLink(userApplication);
if (fromLinks.size() > 1) {
    logger.warn("duplicate user links for {}: {}", userApplication, fromLinks.size());
}

Prevention

When it happens

Trigger: Calling createUserNodeHistogram(userApplication, range, linkList) when the LinkList contains two or more links whose destination is the same user Application — typically duplicated USER->APP links built by overlapping map-builder runs or merged map data.

Common situations: Merging application maps from multiple emitters that each created their own user link; a bug or retry in the link appender duplicating the user->app link; front-end requesting a map for a range where the user link was rebuilt and both old/new links remain in the LinkList.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of pinpoint-apm/pinpoint@744c3d3075 (2026-09-07). Data as JSON: /api/errors/bad133222407032c. Report an issue: GitHub.