Skip to content

NullPointerException on Re-enqueue After Removing Missing File #1001

@alexaungmyooo

Description

@alexaungmyooo

Describe the bug

A java.lang.NullPointerException occurs within the flutter_downloader plugin's native Android DownloadWorker when attempting to enqueue a new download for a file that was previously downloaded, then manually deleted from storage (outside the app), and subsequently had its task record removed using FlutterDownloader.remove(taskId, shouldDeleteContent: true).

This suggests that FlutterDownloader.remove(shouldDeleteContent: true) fails to fully clear the internal state (likely within the underlying Android Download Manager) when the content it's supposed to delete is already missing. This leaves a corrupted or incomplete state, causing subsequent enqueue operations targeting the same file path to crash with a NullPointerException.

To Reproduce

Steps to reproduce the behavior:

Initial Download: Download a file successfully using FlutterDownloader.enqueue(). The file is now present on the device.

Manual File Deletion: Manually delete the physical downloaded file from the device's storage (e.g., using a file manager app). The file is now missing, but your app's internal database still has a record of it.

App-side Record Deletion (of the missing file): In the Flutter app, navigate to the list where downloaded files are displayed. The app will detect that the file is missing for this entry. When prompted (e.g., via a dialog asking to delete or re-download), choose the option to "delete the record" from the app's list. This action internally calls FlutterDownloader.remove(taskId: <original_task_id>, shouldDeleteContent: true).

Attempt Re-download (of the same file): Go to the app's main download list (where new downloads are initiated). Find the same file that was just deleted from the downloaded list. Tap the download button to initiate a new download for it using FlutterDownloader.enqueue().

See error: The download fails, and a java.lang.NullPointerException is observed in the native logs.

Expected behavior

The FlutterDownloader.enqueue() call should successfully start a new download for the file, treating the target path as available, even if a previous task for that path was removed after its content went missing. The NullPointerException should not occur.

Screenshots

N/A

Device information:

✓] Flutter (Channel stable, 3.32.8, on macOS 15.5 24F74 darwin-x64, locale en-GB) [1,475ms]
• Flutter version 3.32.8 on channel stable at /Users/aungmyooo/Development/flutter
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision edada7c56e (6 days ago), 2025-07-25 14:08:03 +0000
• Engine revision ef0cd00091
• Dart version 3.8.1
• DevTools version 2.45.1

[✓] Android toolchain - develop for Android devices (Android SDK version 36.0.0) [8.2s]
• Android SDK at /Users/aungmyooo/Library/Android/sdk
• Platform android-36, build-tools 36.0.0
• Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
This is the JDK bundled with the latest Android Studio installation on this machine.
To manually set the JDK path, use: flutter config --jdk-dir="path/to/jdk".
• Java version OpenJDK Runtime Environment (build 21.0.5+-13047016-b750.29)
• All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 16.4) [3.1s]
• Xcode at /Applications/Xcode.app/Contents/Developer
• Build 16F6
• CocoaPods version 1.16.2

[✓] Chrome - develop for the web [33ms]
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2024.3) [32ms]
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 21.0.5+-13047016-b750.29)

[✓] VS Code (version 1.102.3) [27ms]
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 3.114.0

[✓] Connected device (4 available) [16.5s]
• SM N975F (mobile) • RF8M82Y3K9A • android-arm64 • Android 12 (API 31)
• Aung Myo’s iPhone (wireless) (mobile) • 00008120-0006612E0198A01E • ios • iOS 18.4.1 22E252
• macOS (desktop) • macos • darwin-x64 • macOS 15.5 24F74 darwin-x64
• Chrome (web) • chrome • web-javascript • Google Chrome 138.0.7204.183

[✓] Network resources [1,342ms]
• All expected network resources are available.

• No issues found!

Additional context

The issue does not occur if:

The file exists when FlutterDownloader.remove(shouldDeleteContent: true) is called (i.e., the remove operation successfully deletes the file). In this case, a subsequent enqueue for the same file path works correctly.

A new, unique filename (e.g., by appending a timestamp) is used for the subsequent enqueue operation, even if the original file was missing and its task removed. This workaround bypasses the issue by forcing flutter_downloader to treat each download as truly distinct, avoiding interaction with the corrupted internal state linked to the old, specific file path.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions