{"record":{"id":"76fb1adbaf627bb9","repo":"alibaba/ARouter","slug":"cannot-replace-temporary-arouter-transform-output","errorCode":null,"errorMessage":"Cannot replace temporary ARouter transform output: <temporary>","messagePattern":"Cannot replace temporary ARouter transform output: <temporary>","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"arouter-gradle-plugin/src/main/groovy/com/alibaba/android/arouter/register/core/ScopedClassTransformer.groovy","lineNumber":45,"sourceCode":"\n    static Result transform(Collection<File> jars, Collection<File> directories, File output) {\n        Map<String, Set<String>> implementations = new LinkedHashMap<>()\n        REGISTER_INTERFACES.each { implementations.put(it, new TreeSet<String>()) }\n\n        jars.each { scanJar(it, implementations) }\n        directories.each { scanDirectory(it, implementations) }\n\n        Set<String> registrations = new TreeSet<>()\n        implementations.values().each { registrations.addAll(it) }\n\n        File parent = output.parentFile\n        if (!parent.isDirectory() && !parent.mkdirs()) {\n            throw new IOException('Cannot create ARouter transform output directory: ' + parent)\n        }\n\n        File temporary = new File(parent, output.name + '.tmp')\n        if (temporary.exists() && !temporary.delete()) {\n            throw new IOException('Cannot replace temporary ARouter transform output: ' + temporary)\n        }\n\n        boolean logisticsCenterFound = false\n        Set<String> writtenEntries = new HashSet<>()\n\n        try {\n            JarOutputStream jarOutput = new JarOutputStream(new BufferedOutputStream(new FileOutputStream(temporary)))\n            try {\n                jars.each { File jar ->\n                    logisticsCenterFound |= copyJar(jar, jarOutput, writtenEntries, registrations)\n                }\n                directories.each { File directory ->\n                    logisticsCenterFound |= copyDirectory(directory, jarOutput, writtenEntries, registrations)\n                }\n            } finally {\n                jarOutput.close()\n            }\n","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/alibaba/ARouter/blob/84f451d244e3fb1d0e37801de1b9ee2af2f81d68/arouter-gradle-plugin/src/main/groovy/com/alibaba/android/arouter/register/core/ScopedClassTransformer.groovy#L27-L63","documentation":"Thrown by ScopedClassTransformer when a stale temporary output file (output.name + '.tmp') exists from a previous run and File.delete() fails to remove it. The transform writes to a .tmp file first and renames it, so an undeletable temp file blocks the build with this IOException.","triggerScenarios":"A leftover <output>.tmp file from an interrupted build exists in the output directory and cannot be deleted — file locked by another process/AV scanner, owned by another user, or a read-only filesystem.","commonSituations":"Killing Gradle mid-transform leaving orphaned .tmp files; Windows file locking by antivirus/IDE indexing; parallel builds racing over the same output directory; CI caches restored with wrong ownership.","solutions":["Manually delete the reported <output>.tmp file and rebuild.","Run `./gradlew clean` to wipe stale build outputs.","Ensure no other Gradle daemon/IDE build is running concurrently and that the build dir is writable/owned by the current user."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"File temporary = new File(output.parentFile, output.name + '.tmp')\nif (temporary.exists() && !temporary.canWrite()) {\n    throw new IllegalStateException(\"Stale temp file not deletable: \" + temporary)\n}","typeGuard":null,"tryCatchPattern":"try {\n    transform(...)\n} catch (IOException e) {\n    if (e.message?.contains('Cannot replace temporary ARouter transform output')) {\n        assert new File(e.message.split(': ').last()).delete()\n        // retry the transform once\n    } else throw e\n}","preventionTips":["Delete stale .tmp files with `find build -name '*.tmp' -delete` when builds fail oddly.","Don't run multiple Gradle daemons/builds over the same project directory.","On Windows, exclude build/ from antivirus and IDE indexing locks.","Fix CI cache extraction to preserve file ownership."],"tags":["gradle-plugin","filesystem","io","temp-file"],"backgroundTag":"file-write-failed","analyzedSha":"84f451d244e3fb1d0e37801de1b9ee2af2f81d68","analyzedAt":"2026-09-06T13:30:41.084Z","contentChangedAt":"2026-09-06T13:30:41.084Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}