pinpoint-apm/pinpoint · error · ProfilerException
Transformer already exists. TransformKey:
Error message
Transformer already exists. TransformKey:
What it means
Pinpoint's DefaultDynamicTransformerRegistry stores one ClassFileTransformer per TransformerKey (classloader + internal class name). Because a key uniquely identifies a transformer, registering a second transformer for the same class/classloader pair is treated as a fatal agent configuration error and ProfilerException is thrown.
Source
Thrown at agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/transformer/DefaultDynamicTransformerRegistry.java:72
@Override
public void onTransformRequest(ClassLoader classLoader, String targetClassName, ClassFileTransformer transformer) {
final TransformerKey transformKey = createTransformKey(classLoader, targetClassName);
add(transformKey, transformer);
if (logger.isInfoEnabled()) {
logger.info("added dynamic transformer classLoader: {}, className: {}, registry size: {}", classLoader, targetClassName, transformerMap.size());
}
}
private void add(TransformerKey key, ClassFileTransformer transformer) {
final ClassFileTransformer prev = transformerMap.putIfAbsent(key, transformer);
if (prev != null) {
throw new ProfilerException("Transformer already exists. TransformKey: " + key + ", transformer: " + prev);
}
}
private TransformerKey createTransformKey(ClassLoader classLoader, String targetClassName) {
final String classInternName = JavaAssistUtils.javaNameToJvmName(targetClassName);
return new TransformerKey(classLoader, classInternName);
}
private TransformerKey createTransformKey(Class<?> targetClass) {
final ClassLoader classLoader = targetClass.getClassLoader();
final String targetClassName = targetClass.getName();
return createTransformKey(classLoader, targetClassName);
}
@Override
public ClassFileTransformer getTransformer(ClassLoader classLoader, String targetClassName) {View on GitHub (pinned to 744c3d3075)
Solutions
- Check that only one transformer is registered for the target class (inspect plugin/transformer config for duplicates)
- Use the existing transformer already registered for that key instead of adding a new one
- If replacement is intended, remove/replace the entry rather than add
- Deduplicate transformer registration at startup (track registered keys)
Example fix
// before
registry.addTransformer(classLoader, "com.foo.Bar", newTransformer);
registry.addTransformer(classLoader, "com.foo.Bar", otherTransformer); // throws
// after
if (registry.getTransformer(classLoader, "com.foo.Bar") == null) {
registry.addTransformer(classLoader, "com.foo.Bar", newTransformer);
} Defensive patterns
Strategy: validation
Validate before calling
if (existingRegistry.contains(classLoader, internalClassName)) { logger.warn("Transformer already registered for {}", internalClassName); return; } Type guard
// Java: check before registering boolean alreadyRegistered = transformerMap.containsKey(new TransformerKey(classLoader, javaInternName));
Prevention
- Deduplicate transformer registration at startup
- Keep a single registry entry point so plugins cannot double-register
- Log registered TransformerKeys to spot duplicates early
When it happens
Trigger: Calling add()/registering a dynamic transformer whose (classLoader, targetClassName) pair is already present in transformerMap; putIfAbsent returns the previous non-null transformer.
Common situations: Two plugins or pinpoint config entries both instrumenting the same target class; applying a transform script twice to the same class; re-registering a transformer after a config reload without clearing the registry.
Related errors
- unknown scanner type classLoader:${classLoader} protectionDo
- ${className} define fail Caused by:${causeMessage}
- J9BootLoader create fail Caused by:
- initialize fail Caused by:
- invoke fail Caused by:
AI-assisted analysis of pinpoint-apm/pinpoint@744c3d3075 (2026-09-07).
Data as JSON: /api/errors/5d4ac4d09d8ac60e.
Report an issue: GitHub.