alibaba/ARouter · error · IOException
Cannot replace temporary ARouter transform output: <temporar
Error message
Cannot replace temporary ARouter transform output: <temporary>
What it means
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.
Source
Thrown at arouter-gradle-plugin/src/main/groovy/com/alibaba/android/arouter/register/core/ScopedClassTransformer.groovy:45
static Result transform(Collection<File> jars, Collection<File> directories, File output) {
Map<String, Set<String>> implementations = new LinkedHashMap<>()
REGISTER_INTERFACES.each { implementations.put(it, new TreeSet<String>()) }
jars.each { scanJar(it, implementations) }
directories.each { scanDirectory(it, implementations) }
Set<String> registrations = new TreeSet<>()
implementations.values().each { registrations.addAll(it) }
File parent = output.parentFile
if (!parent.isDirectory() && !parent.mkdirs()) {
throw new IOException('Cannot create ARouter transform output directory: ' + parent)
}
File temporary = new File(parent, output.name + '.tmp')
if (temporary.exists() && !temporary.delete()) {
throw new IOException('Cannot replace temporary ARouter transform output: ' + temporary)
}
boolean logisticsCenterFound = false
Set<String> writtenEntries = new HashSet<>()
try {
JarOutputStream jarOutput = new JarOutputStream(new BufferedOutputStream(new FileOutputStream(temporary)))
try {
jars.each { File jar ->
logisticsCenterFound |= copyJar(jar, jarOutput, writtenEntries, registrations)
}
directories.each { File directory ->
logisticsCenterFound |= copyDirectory(directory, jarOutput, writtenEntries, registrations)
}
} finally {
jarOutput.close()
}
View on GitHub (pinned to 84f451d244)
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.
Defensive patterns
Strategy: try-catch
Validate before calling
File temporary = new File(output.parentFile, output.name + '.tmp')
if (temporary.exists() && !temporary.canWrite()) {
throw new IllegalStateException("Stale temp file not deletable: " + temporary)
} Try / catch
try {
transform(...)
} catch (IOException e) {
if (e.message?.contains('Cannot replace temporary ARouter transform output')) {
assert new File(e.message.split(': ').last()).delete()
// retry the transform once
} else throw e
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.
Related errors
- Cannot create ARouter transform output directory: <parent>
- Missing extracted secondary dex file '<path>'
- ARouter::Register >>> LogisticsCenter.class was not found; a
AI-assisted analysis of alibaba/ARouter@84f451d244 (2026-09-06).
Data as JSON: /api/errors/76fb1adbaf627bb9.
Report an issue: GitHub.