{"record":{"id":"5d4ac4d09d8ac60e","repo":"pinpoint-apm/pinpoint","slug":"transformer-already-exists-transformkey","errorCode":null,"errorMessage":"Transformer already exists. TransformKey: ","messagePattern":"Transformer already exists\\. TransformKey: ","errorType":"exception","errorClass":"ProfilerException","httpStatus":null,"severity":"error","filePath":"agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/transformer/DefaultDynamicTransformerRegistry.java","lineNumber":72,"sourceCode":"\n\n    @Override\n    public void onTransformRequest(ClassLoader classLoader, String targetClassName, ClassFileTransformer transformer) {\n\n\n        final TransformerKey transformKey = createTransformKey(classLoader, targetClassName);\n        add(transformKey, transformer);\n\n        if (logger.isInfoEnabled()) {\n            logger.info(\"added dynamic transformer classLoader: {}, className: {}, registry size: {}\", classLoader, targetClassName, transformerMap.size());\n        }\n    }\n\n    private void add(TransformerKey key, ClassFileTransformer transformer) {\n        final ClassFileTransformer prev = transformerMap.putIfAbsent(key, transformer);\n        \n        if (prev != null) {\n            throw new ProfilerException(\"Transformer already exists. TransformKey: \" + key + \", transformer: \" + prev);\n        }\n    }\n\n    private TransformerKey createTransformKey(ClassLoader classLoader, String targetClassName) {\n        final String classInternName = JavaAssistUtils.javaNameToJvmName(targetClassName);\n        return new TransformerKey(classLoader, classInternName);\n    }\n\n    private TransformerKey createTransformKey(Class<?> targetClass) {\n\n        final ClassLoader classLoader = targetClass.getClassLoader();\n        final String targetClassName = targetClass.getName();\n\n        return createTransformKey(classLoader, targetClassName);\n    }\n\n    @Override\n    public ClassFileTransformer getTransformer(ClassLoader classLoader, String targetClassName) {","sourceCodeStart":54,"sourceCodeEnd":90,"githubUrl":"https://github.com/pinpoint-apm/pinpoint/blob/744c3d3075e595656abb1ae331ad2c0e4c9eb996/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/transformer/DefaultDynamicTransformerRegistry.java#L54-L90","documentation":"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.","triggerScenarios":"Calling add()/registering a dynamic transformer whose (classLoader, targetClassName) pair is already present in transformerMap; putIfAbsent returns the previous non-null transformer.","commonSituations":"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.","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)"],"exampleFix":"// before\nregistry.addTransformer(classLoader, \"com.foo.Bar\", newTransformer);\nregistry.addTransformer(classLoader, \"com.foo.Bar\", otherTransformer); // throws\n// after\nif (registry.getTransformer(classLoader, \"com.foo.Bar\") == null) {\n    registry.addTransformer(classLoader, \"com.foo.Bar\", newTransformer);\n}","handlingStrategy":"validation","validationCode":"if (existingRegistry.contains(classLoader, internalClassName)) { logger.warn(\"Transformer already registered for {}\", internalClassName); return; }","typeGuard":"// Java: check before registering\nboolean alreadyRegistered = transformerMap.containsKey(new TransformerKey(classLoader, javaInternName));","tryCatchPattern":null,"preventionTips":["Deduplicate transformer registration at startup","Keep a single registry entry point so plugins cannot double-register","Log registered TransformerKeys to spot duplicates early"],"tags":["java","classloader","instrumentation","duplicate-registration"],"backgroundTag":"duplicate-registration","analyzedSha":"744c3d3075e595656abb1ae331ad2c0e4c9eb996","analyzedAt":"2026-09-07T18:48:45.289Z","contentChangedAt":"2026-09-07T18:48:45.289Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}