google/ExoPlayer · error · IllegalStateException

Could not delete the previous export output file

Error message

Could not delete the previous export output file

What it means

Thrown by TransformerActivity.createExternalCacheFile when a previous export output file exists in the app's external cache dir but File.delete() returns false. This is a demo-activity guard that resets the output file before a new export so Transformer does not append to or fail on stale output. The delete fails when something still holds the file open or the storage is in a bad state.

Source

Thrown at demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/TransformerActivity.java:360

                TransformerActivity.this.onCompleted(inputUri, filePath);
              }

              @Override
              public void onError(
                  Composition composition,
                  ExportResult exportResult,
                  ExportException exportException) {
                TransformerActivity.this.onError(exportException);
              }
            })
        .build();
  }

  /** Creates a cache file, resetting it if it already exists. */
  private File createExternalCacheFile(String fileName) throws IOException {
    File file = new File(getExternalCacheDir(), fileName);
    if (file.exists() && !file.delete()) {
      throw new IllegalStateException("Could not delete the previous export output file");
    }
    if (!file.createNewFile()) {
      throw new IllegalStateException("Could not create the export output file");
    }
    return file;
  }

  @RequiresNonNull({
    "inputCardView",
    "outputPlayerView",
    "exportStopwatch",
    "progressViewGroup",
  })
  private Composition createComposition(MediaItem mediaItem, @Nullable Bundle bundle)
      throws PackageManager.NameNotFoundException {
    EditedMediaItem.Builder editedMediaItemBuilder = new EditedMediaItem.Builder(mediaItem);
    // For image inputs. Automatically ignored if input is audio/video.
    editedMediaItemBuilder.setDurationUs(5_000_000).setFrameRate(30);

View on GitHub (pinned to dd430f7053)

Solutions

  1. Release any Player and Transformer instance (and stop playback of the output file) before creating a new export file
  2. Check file.canWrite() and external storage state before export; surface a user-facing message instead of crashing
  3. Retry the delete once after a short delay, or fall back to a uniquely named file (e.g. append System.currentTimeMillis()) when deletion keeps failing
  4. Call file.delete() in onDestroy/onStop so the demo starts clean next time

Example fix

// before
if (file.exists() && !file.delete()) {
  throw new IllegalStateException("Could not delete the previous export output file");
}

// after: release the player that holds the file, then retry with a unique name
if (file.exists() && !file.delete()) {
  String unique = fileName + '-' + System.currentTimeMillis();
  file = new File(getExternalCacheDir(), unique);
}
if (!file.createNewFile()) {
  throw new IllegalStateException("Could not create the export output file");
}
Defensive patterns

Strategy: try-catch

Validate before calling

File file = new File(context.getExternalCacheDir(), fileName);
if (file.exists() && (!file.canWrite() || !file.delete())) {
  // do not proceed: someone still holds the file or storage is bad
  return new File(context.getExternalCacheDir(),
      System.currentTimeMillis() + "-" + fileName);
}

Try / catch

try {
  File out = createExternalCacheFile(fileName);
} catch (IllegalStateException e) {
  // message tells which step failed; release players and retry with a unique name
  releasePlayersAndTransformer();
  File out = new File(getExternalCacheDir(),
      System.currentTimeMillis() + "-" + fileName);
}

Prevention

When it happens

Trigger: Calling startExport/createExternalCacheFile while a previous export's output file is still open by a Player or Transformer; running a second export before releasing the output player; external cache dir mounted read-only or full; file deleted concurrently between exists() and delete().

Common situations: User re-exports immediately after a previous run while the output PlayerView still plays the old file; process crashed leaving a locked file; device storage pressure; permissions changed on getExternalCacheDir().

Related errors


AI-assisted analysis of google/ExoPlayer@dd430f7053 (2026-08-14). Data as JSON: /api/errors/afc272eb061fca3c. Report an issue: GitHub.