Tencent/matrix · error · RuntimeException

Input file( ) should not be same with output!

Error message

Input file(${classFile.getCanonicalPath()}) should not be same with output!

What it means

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.

Solutions

  1. Ensure the output directory passed to the transform differs from the input directory
  2. Avoid symlinked directories (or use real canonical paths) when configuring input/output dirs
  3. Check incremental build state: clean the module (gradle clean) to reset stale transform directories
  4. Verify the plugin's directory provider maps input to a distinct output location per AGP Transform API contract

Example fix

// before
File output = input // same dir
// after
File output = new File(input.getParentFile(), input.getName() + '-traced')
assert output.canonicalPath != input.canonicalPath
Defensive patterns

Strategy: validation

Validate before calling

if (inputDir.canonicalPath == outputDir.canonicalPath) {
    throw new IllegalArgumentException('transform input and output directories must differ')
}

Try / catch

try {
    methodTracer.trace(srcMap, jarList, classLoader, false)
} catch (RuntimeException e) {
    if (e.message?.contains('should not be same with output')) {
        logger.error('Input/output directory collision: use distinct transform output directories, avoid symlinks', e)
    }
    throw e
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of Tencent/matrix@3b8293bd65 (2026-09-08). Data as JSON: /api/errors/a57e67b5a85a62c2. Report an issue: GitHub.

Appendix: source

Thrown at matrix/matrix-android/matrix-gradle-plugin/src/main/java/com/tencent/matrix/trace/MethodTracer.java:139

    private void innerTraceMethodFromSrc(File input, File output, ClassLoader classLoader, boolean ignoreCheckClass) {

        ArrayList<File> classFileList = new ArrayList<>();
        if (input.isDirectory()) {
            listClassFiles(classFileList, input);
        } else {
            classFileList.add(input);
        }

        for (File classFile : classFileList) {
            InputStream is = null;
            FileOutputStream os = null;
            try {
                final String changedFileInputFullPath = classFile.getAbsolutePath();
                final File changedFileOutput = new File(changedFileInputFullPath.replace(input.getAbsolutePath(), output.getAbsolutePath()));

                if (changedFileOutput.getCanonicalPath().equals(classFile.getCanonicalPath())) {
                    throw new RuntimeException("Input file(" + classFile.getCanonicalPath() + ") should not be same with output!");
                }

                if (!changedFileOutput.exists()) {
                    changedFileOutput.getParentFile().mkdirs();
                }
                changedFileOutput.createNewFile();

                if (MethodCollector.isNeedTraceFile(classFile.getName())) {

                    is = new FileInputStream(classFile);
                    ClassReader classReader = new ClassReader(is);
                    ClassWriter classWriter = new TraceClassWriter(ClassWriter.COMPUTE_FRAMES, classLoader);
                    ClassVisitor classVisitor = new TraceClassAdapter(AgpCompat.getAsmApi(), classWriter);
                    classReader.accept(classVisitor, ClassReader.EXPAND_FRAMES);
                    is.close();

                    byte[] data = classWriter.toByteArray();

View on GitHub (pinned to 3b8293bd65)