pinpoint-apm/pinpoint · error · IllegalArgumentException

Invalid linkKey format: expected 'fromApp~toApp' but got:

Error message

Invalid linkKey format: expected 'fromApp~toApp' but got: 

What it means

ServerMapHistogramController.getLinkTimeHistogramData validates the `linkKey` request parameter against the regex ^[^~]+~[^~]+$ before parsing it into a from/to application pair. This error is thrown when the supplied linkKey does not contain exactly two '~'-separated non-empty segments (e.g. it is empty, null-ish, or lacks the '~' separator). The controller refuses to proceed because it cannot split the key into fromApp and toApp applications.

Source

Thrown at web/src/main/java/com/navercorp/pinpoint/web/applicationmap/controller/ServerMapHistogramController.java:360

    }

    @GetMapping(value = "/statistics/links")
    public LinkHistogramSummaryView getLinkTimeHistogramData(
            @ServiceParam ServiceName serviceName,
            @Valid @ModelAttribute
            ApplicationForm appForm,
            @Valid @ModelAttribute
            RangeForm rangeForm,
            @Valid @ModelAttribute
            SearchOptionForm searchForm,
            @RequestParam("linkKey") @NotBlank String linkKey
    ) {
        final Range range = toRange(rangeForm);
        this.rangeValidator.validate(range);
        TimeWindow timeWindow = new TimeWindow(range);

        if (!LINK_KEY_VALIDATION_PATTERN.matcher(linkKey).matches()) {
            throw new IllegalArgumentException("Invalid linkKey format: expected 'fromApp~toApp' but got: " + linkKey);
        }
        String[] parts = LINK_DELIMITER_PATTERN.split(linkKey, 2);
        if (parts.length != 2) {
            throw new IllegalArgumentException("Invalid linkKey format: expected 'fromApp~toApp' but got: " + linkKey);
        }
        final Service service = serviceModelResolver.getService(serviceName.getName());
        final Application fromApplication = this.newApplication(service, parts[0]);
        final Application toApplication = this.newApplication(service, parts[1]);

        final LinkHistogramSummary linkHistogramSummary =
                histogramService.selectLinkHistogramData(fromApplication, toApplication, timeWindow);

        return new LinkHistogramSummaryView(linkHistogramSummary, timeWindow, TimeHistogramView.TimeseriesHistogram);
    }
}

View on GitHub (pinned to 744c3d3075)

Solutions

  1. Pass the linkKey exactly as returned by the server-map data endpoint (format 'fromAppName~toAppName'), e.g. linkKey=FRONT~BACK
  2. Ensure the request actually includes the linkKey parameter; empty string fails the same validation
  3. Verify the two application names are non-empty and contain no '~' characters themselves; if an app name can contain '~', URL-encode it or pick a different delimiter path
  4. Check the client code that constructs the key — it must join exactly two non-empty segments with a single '~'

Example fix

// before
const linkKey = fromApp + toApp; // missing separator
const url = `/getLinkTimeHistogramData?linkKey=${linkKey}`;
// after
const linkKey = `${fromApp}~${toApp}`;
if (!fromApp || !toApp) throw new Error('fromApp and toApp are required');
const url = `/getLinkTimeHistogramData?linkKey=${encodeURIComponent(linkKey)}`;
Defensive patterns

Strategy: validation

Validate before calling

function isValidLinkKey(linkKey) {
  return typeof linkKey === 'string' && /^[^~]+~[^~]+$/.test(linkKey);
}
if (!isValidLinkKey(linkKey)) throw new Error('linkKey must be fromApp~toApp');

Type guard

function isLinkKey(v) {
  return typeof v === 'string' && /^[^~]+~[^~]+$/.test(v);
}

Try / catch

try {
  const data = await api.getLinkTimeHistogramData({ linkKey });
} catch (e) {
  if (e.status === 400 && String(e.message).includes('Invalid linkKey format')) {
    // refresh linkKey from the server-map response and retry once
  } else { throw e; }
}

Prevention

When it happens

Trigger: GET/POST to the link time-histogram endpoint (getLinkTimeHistogramData) with a missing, empty, or malformed `linkKey` parameter — e.g. linkKey='', linkKey='myApp' (no '~'), or a key containing multiple '~' characters or empty sides like '~toApp' / 'fromApp~'.

Common situations: Frontend code building the link key by hand instead of using the node/link keys returned by the server-map API; URL-encoding issues that strip or mangle the '~'; a UI bug passing an undefined linkKey after a map refresh; API consumers guessing the key format instead of copying it verbatim from a previous server-map response.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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