pinpoint-apm/pinpoint · error · RuntimeException
AnnotationKey code of
Error message
AnnotationKey code of ${pair} is duplicated with ${prev} What it means
TraceMetadataLoader.check registers AnnotationKeys into a code->pair map while loading TraceMetadataProviders. If two providers declare AnnotationKeys with the same integer code, the second put returns the previous entry and this RuntimeException is thrown, aborting metadata loading. It is a deliberate duplicate-registration guard so annotation codes stay unambiguous across providers.
Solutions
- Find the two AnnotationKey definitions named in the message and change your custom key's code to an unused value (use AnnotationKeyFactory / pick a code outside Pinpoint's reserved ranges, e.g. a high vendor range).
- Check the classpath for duplicate plugin jars or stale old versions of your provider and remove them.
- Verify all TraceMetadataProviders registered via ServiceLoader are intentional; remove test/development providers from the deployment.
Example fix
// before public static final AnnotationKey MY_KEY = AnnotationKeyFactory.of(1200, "MY_KEY"); // after public static final AnnotationKey MY_KEY = AnnotationKeyFactory.of(9500, "MY_KEY"); // unused code
Defensive patterns
Strategy: validation
Validate before calling
// before loading, ensure unique codes across providers
Map<Integer, String> seen = new HashMap<>();
for (AnnotationKey key : myProvider.getAnnotationKeys()) {
String prev = seen.putIfAbsent(key.getCode(), key.getName());
if (prev != null) throw new IllegalStateException("Duplicate AnnotationKey code " + key.getCode());
seen.put(key.getCode(), key.getName());
} Try / catch
try {
loader.load(provider);
} catch (RuntimeException e) {
if (e.getMessage() != null && e.getMessage().contains("is duplicated with")) {
logger.error("Duplicate AnnotationKey code in provider", e); // fail fast, fix codes
} else { throw e; }
} Prevention
- Pick custom AnnotationKey codes from a documented unused high range (never reuse built-in Pinpoint codes).
- Grep the classpath/plugins for duplicate provider jars before deployment.
- Keep a central registry of assigned codes across your team's plugins.
- Write a unit test that loads all your providers and asserts no duplicate codes.
When it happens
Trigger: Calling TraceMetadataLoader.load (via ServiceTypeRegistry/AnnotationKeyRegistry building) when two loaded TraceMetadataProvider implementations both return AnnotationKey objects with the same getCode() value from their addAnnotationKeys/addAllAnnotationKeys callbacks.
Common situations: A plugin bundle and a custom provider both define AnnotationKey with a hand-picked code that collides with Pinpoint's built-in codes (e.g. reusing code 1/10/9000); two versions of a plugin jar on the classpath each registering the same keys; copy-pasting an AnnotationKey definition and forgetting to change the code.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- banner IO failed
- boot class not found. bootClass: Error:
- Either tagGroupList or fieldNameList must have a size of…
- Failed to detect pinpoint profile. Please add…
- I/O error getting type provider definitions
AI-assisted analysis of pinpoint-apm/pinpoint@744c3d3075 (2026-09-07).
Data as JSON: /api/errors/69da206eec32745d.
Report an issue: GitHub.
Appendix: source
Thrown at commons-profiler/src/main/java/com/navercorp/pinpoint/common/profiler/trace/TraceMetadataLoader.java:260
logger.info(serviceTypePairToString(serviceType));
}
}
private int getCode(Pair<ServiceType> p) {
return p.value.getCode();
}
}
private class AnnotationKeyChecker {
private final Map<Integer, Pair<AnnotationKey>> annotationKeyCodeMap = new HashMap<>();
private void check(AnnotationKey key, TraceMetadataProvider provider) {
Pair<AnnotationKey> pair = new Pair<>(key, provider);
Pair<AnnotationKey> prev = annotationKeyCodeMap.put(key.getCode(), pair);
if (prev != null) {
// TODO change exception type
throw new RuntimeException("AnnotationKey code of " + annotationKeyPairToString(pair) + " is duplicated with " + annotationKeyPairToString(prev));
}
}
private void logResult() {
logger.info("Finished loading AnnotationKeys:");
List<Pair<AnnotationKey>> annotationKeys = new ArrayList<>(annotationKeyCodeMap.values());
annotationKeys.sort(Comparator.comparingInt(this::getCode));
for (Pair<AnnotationKey> annotationKey : annotationKeys) {
logger.info(annotationKeyPairToString(annotationKey));
}
}
private int getCode(Pair<AnnotationKey> a) {
return a.value.getCode();
}
}View on GitHub (pinned to 744c3d3075)