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

  1. Check that only one transformer is registered for the target class (inspect plugin/transformer config for duplicates)
  2. Use the existing transformer already registered for that key instead of adding a new one
  3. If replacement is intended, remove/replace the entry rather than add
  4. 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

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


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