Skip to content

Incorrect "not enough space" error during move operations #473

Description

@akbudakanl

Checklist

  • I can reproduce the bug with the latest version given here.
  • I made sure that there are no existing issues - open or closed - to which I could contribute my information.
  • I made sure that there are no existing discussions - open or closed - to which I could contribute my information.
  • I have read the FAQs inside the app (Menu -> About -> FAQs) and my problem isn't listed.
  • I have taken the time to fill in all the required details. I understand that the bug report will be dismissed otherwise.
  • This issue contains only one bug.
  • I have read and understood the contribution guidelines.

Affected app version

1.6.1 (Latest)

Affected Android/Custom ROM version

Android 13

Affected device model

Samsung Galaxy S20

How did you install the app?

Google Play Store

Steps to reproduce the bug

Scenario: Move blocked by false space check

  • Have a device/emulator with 30 GB free space
  • Select a 50 GB file (or folder with 50 GB total)
  • Create an empty folder /storage/emulated/0/Folder A
  • In Fossify File Manager, select the 50 GB file/folder → Move to → select Folder A
  • Expected: File is moved instantly (metadata rename, no space needed)
  • Actual: "Not enough space" error

Expected behavior

As highlighted in the scenarios shared under the heading "Reproduction Steps", during the file transfer process, if the file is moved, this should happen instantly. Move operations should not require free space — When moving files/folders within the same storage volume, no additional disk space is consumed (it's essentially a rename/pointer change), yet the app performs the same space check as copy operations.

Note

On extreme low-storage edge cases: A same-volume rename() syscall does require a negligible amount of filesystem metadata space (typically a few KB regardless of file size). Rather than pre-checking this with a file-size comparison (which is always wrong for moves), the correct approach is to attempt the operation and surface any OS-level ENOSPC error to the user. This is the standard behavior in other major file managers

Actual behavior

Moving operations require free space—it performs the same space check as copying operations within the same storage volume.

Screenshots/Screen recordings

Since I reset my phone some time after identifying this problem, I currently have plenty of free space, and unfortunately, I cannot reproduce the issue. I apologize for not having a screenshot.

Additional information

Root Cause Analysis

The bug originates in the Fossify Commons library, specifically in the startCopyMove() function inside BaseSimpleActivity.kt.

The startCopyMove function does not distinguish between copy and move operations when checking available space. The isCopyOperation parameter exists but is never consulted before the space comparison.

private fun startCopyMove(...) {
    val availableSpace = destinationPath.getAvailableStorageB()
    val sumToCopy = files.sumByLong { it.getProperSize(applicationContext, copyHidden) }

    // ❌ Performs space check for BOTH copy and move operations
    if (availableSpace == -1L || sumToCopy < availableSpace) {
        // ... proceeds ...
    } else {
        // ❌ Aborts the move operation if sumToCopy > availableSpace
        val text = String.format(getString(R.string.no_space), ...)
        toast(text, Toast.LENGTH_LONG)
    }
}

Cross-volume moves (e.g., internal → SD card) are actually a copy+delete and DO need free space on the destination. The fix should ideally bypass the space check when source and destination share the same mount point / storage volume, or simply attempt the operation and catch OS errors.

Suggested Fix

The fix should be applied in BaseSimpleActivity.startCopyMove() in the Fossify Commons library. The function needs to check if the operation actually requires additional space before performing the space calculation and validation:

private fun startCopyMove(...) {
    // Step 1: Determine if space check is needed
    // Moves within the same volume do not require additional space
    val needsSpaceCheck = isCopyOperation || 
        !isSameStorageVolume(files.first().path, destinationPath)
        
    if (needsSpaceCheck) {
        val availableSpace = destinationPath.getAvailableStorageB()
        val sumToCopy = files.sumByLong { it.getProperSize(applicationContext, copyHidden) }
        
        // Step 2: Abort if not enough space
        if (availableSpace != -1L && sumToCopy >= availableSpace) {
            val text = String.format(
                getString(R.string.no_space),
                sumToCopy.formatSize(),
                availableSpace.formatSize()
            )
            toast(text, Toast.LENGTH_LONG)
            return
        }
    }
    
    // Step 3: Proceed with operation safely
    checkConflicts(files, destinationPath, 0, LinkedHashMap()) { conflictResolutions ->
        toast(if (isCopyOperation) R.string.copying else R.string.moving)
        val pair = Pair(files, destinationPath)
        CopyMoveTask(
            activity = this,
            isCopyOperation = isCopyOperation,
            copyPhotoVideoOnly = copyPhotoVideoOnly,
            conflictResolutions = conflictResolutions,
            listener = copyMoveListener,
            copyHidden = copyHidden
        ).execute(pair)
    }
}
Related Files
File Repository Role
BaseSimpleActivity.kt FossifyOrg/commons Contains startCopyMove() which performs the flawed space check
ItemsAdapter.kt FossifyOrg/File-Manager Calls activity.copyMoveFilesTo()

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething is not workingneeds triageIssue is not yet ready for PR authors to take up

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions