{"record":{"id":"a57e67b5a85a62c2","repo":"Tencent/matrix","slug":"input-file-classfile-getcanonicalpath-should","errorCode":null,"errorMessage":"Input file(${classFile.getCanonicalPath()}) should not be same with output!","messagePattern":"Input file\\((.+?)\\) should not be same with output!","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"matrix/matrix-android/matrix-gradle-plugin/src/main/java/com/tencent/matrix/trace/MethodTracer.java","lineNumber":139,"sourceCode":"\n    private void innerTraceMethodFromSrc(File input, File output, ClassLoader classLoader, boolean ignoreCheckClass) {\n\n        ArrayList<File> classFileList = new ArrayList<>();\n        if (input.isDirectory()) {\n            listClassFiles(classFileList, input);\n        } else {\n            classFileList.add(input);\n        }\n\n        for (File classFile : classFileList) {\n            InputStream is = null;\n            FileOutputStream os = null;\n            try {\n                final String changedFileInputFullPath = classFile.getAbsolutePath();\n                final File changedFileOutput = new File(changedFileInputFullPath.replace(input.getAbsolutePath(), output.getAbsolutePath()));\n\n                if (changedFileOutput.getCanonicalPath().equals(classFile.getCanonicalPath())) {\n                    throw new RuntimeException(\"Input file(\" + classFile.getCanonicalPath() + \") should not be same with output!\");\n                }\n\n                if (!changedFileOutput.exists()) {\n                    changedFileOutput.getParentFile().mkdirs();\n                }\n                changedFileOutput.createNewFile();\n\n                if (MethodCollector.isNeedTraceFile(classFile.getName())) {\n\n                    is = new FileInputStream(classFile);\n                    ClassReader classReader = new ClassReader(is);\n                    ClassWriter classWriter = new TraceClassWriter(ClassWriter.COMPUTE_FRAMES, classLoader);\n                    ClassVisitor classVisitor = new TraceClassAdapter(AgpCompat.getAsmApi(), classWriter);\n                    classReader.accept(classVisitor, ClassReader.EXPAND_FRAMES);\n                    is.close();\n\n                    byte[] data = classWriter.toByteArray();\n","sourceCodeStart":121,"sourceCodeEnd":157,"githubUrl":"https://github.com/Tencent/matrix/blob/3b8293bd65d47eeea7caf1f32a3a5d4d5eab60e7/matrix/matrix-android/matrix-gradle-plugin/src/main/java/com/tencent/matrix/trace/MethodTracer.java#L121-L157","documentation":"Thrown by MethodTracer.innerTraceMethodFromSrc when the computed output file path is canonically identical to the input class file, which would mean overwriting the input in place — an invariant the tracer forbids. The output path is derived by string-replacing the input dir with the output dir, so identical canonical paths indicate the transform mapped the file onto itself.","triggerScenarios":"Calling the trace transform with input directory equal to the output directory (or output nested/symlinked so canonical paths coincide), so changedFileOutput resolves to the same file as the input class.","commonSituations":"Misconfigured incremental transform directories where the plugin passes the same folder for input and output; symlinked build directories (e.g. macOS /tmp symlink to /private/tmp) making distinct paths canonically equal.","solutions":["Ensure the output directory passed to the transform differs from the input directory","Avoid symlinked directories (or use real canonical paths) when configuring input/output dirs","Check incremental build state: clean the module (gradle clean) to reset stale transform directories","Verify the plugin's directory provider maps input to a distinct output location per AGP Transform API contract"],"exampleFix":"// before\nFile output = input // same dir\n// after\nFile output = new File(input.getParentFile(), input.getName() + '-traced')\nassert output.canonicalPath != input.canonicalPath","handlingStrategy":"validation","validationCode":"if (inputDir.canonicalPath == outputDir.canonicalPath) {\n    throw new IllegalArgumentException('transform input and output directories must differ')\n}","typeGuard":null,"tryCatchPattern":"try {\n    methodTracer.trace(srcMap, jarList, classLoader, false)\n} catch (RuntimeException e) {\n    if (e.message?.contains('should not be same with output')) {\n        logger.error('Input/output directory collision: use distinct transform output directories, avoid symlinks', e)\n    }\n    throw e\n}","preventionTips":["Always provide a distinct output directory from the transform API (getSecondaryFiles/output mapping)","Avoid symlinked build paths that make different paths canonically equal","Run gradle clean when switching transform configurations to clear stale incremental state"],"tags":["gradle-plugin","bytecode-instrumentation","path-collision","method-tracer"],"backgroundTag":"invalid-argument-value","analyzedSha":"3b8293bd65d47eeea7caf1f32a3a5d4d5eab60e7","analyzedAt":"2026-09-08T08:01:39.722Z","contentChangedAt":"2026-09-08T08:01:39.722Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}