Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

java.io.FileNotFoundException: open failed: ENOSPC (No space left on device) #5802

Closed
mrblrrd opened this issue Mar 25, 2024 · 6 comments
Closed

Comments

@mrblrrd
Copy link

mrblrrd commented Mar 25, 2024

[READ] Step 1: Are you in the right place?

Issues filed here should be about bugs in the code in this repository.
If you have a general question, need help debugging, or fall into some
other category use one of these other channels:

  • For general technical questions, post a question on StackOverflow
    with the firebase tag.
  • For general Firebase discussion, use the firebase-talk
    google group.
  • For help troubleshooting your application that does not fall under one
    of the above categories, reach out to the personalized
    Firebase support channel.

[REQUIRED] Step 2: Describe your environment

  • Android Studio version: Iguana | 2023.2.1 Patch 1
  • Firebase Component: Crashlytics
  • Component version: 18.6.2

[REQUIRED] Step 3: Describe the problem

Steps to reproduce:

Fatal Exception: java.io.FileNotFoundException: /data/user/0/<package>/files/datastore/firebase_session_Y29tLnZrb250YWt0ZS5hbmRyb2lk_data.preferences_pb.tmp: open failed: ENOSPC (No space left on device)
       at libcore.io.IoBridge.open(IoBridge.java:574)
       at java.io.FileOutputStream.<init>(FileOutputStream.java:236)
       at java.io.FileOutputStream.<init>(FileOutputStream.java:186)
       at androidx.datastore.core.SingleProcessDataStore.writeData$datastore_core(SingleProcessDataStore.kt:425)
       at androidx.datastore.core.SingleProcessDataStore.transformAndWrite(SingleProcessDataStore.kt:410)
       at androidx.datastore.core.SingleProcessDataStore.access$getFile(SingleProcessDataStore.kt:76)
       at androidx.datastore.core.SingleProcessDataStore.access$transformAndWrite(SingleProcessDataStore.kt:76)
       at androidx.datastore.core.SingleProcessDataStore$transformAndWrite$1.invokeSuspend(SingleProcessDataStore.kt:13)
       at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
       at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108)
       at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:115)
       at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:103)
       at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:793)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:697)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:684)

Relevant Code:

No specific code.

@argzdev
Copy link
Contributor

argzdev commented Apr 2, 2024

Hi @mrblrrd, thanks for reaching out. It looks like the issue is due to the device not having enough memory left in the internal storage. Does this happen even with fair amount of internal memory within the device? Also is this occurring on multiple devices?

@mrblrrd
Copy link
Author

mrblrrd commented Apr 3, 2024

Yes, this is due to lack of disk space. I believe this should not lead to a crash of the application. We see a noticeable increase in such crashes in our prod application on Crashlytics Dashboard after updating to version 18.6.2. Different devices: Redmi 9T, Honor X7a, Redmi Note 10S, Galaxy A12, etc.

@argzdev
Copy link
Contributor

argzdev commented Apr 3, 2024

Thanks for the extra details, @mrblrrd. What was the previous version of Crashlytics did you use prior to encounter this issue? Any chance you could share the full stacktrace? I'm having a hard time pin pointing in which part of Crashlytics is triggering the issue.

@mrblrrd
Copy link
Author

mrblrrd commented Apr 3, 2024

The previous version was 18.3.3. The stack trace above is full. I can give you another recent example:

Fatal Exception: java.io.FileNotFoundException
/data/user/0/<package>/files/datastore/firebase_session_Y29tLnZrb250YWt0ZS5hbmRyb2lk_data.preferences_pb.tmp: open failed: ENOSPC (No space left on device)

Fatal Exception: java.io.FileNotFoundException: /data/user/0/<package>/files/datastore/firebase_session_Y29tLnZrb250YWt0ZS5hbmRyb2lk_data.preferences_pb.tmp: open failed: ENOSPC (No space left on device)
       at libcore.io.IoBridge.open(IoBridge.java:492)
       at java.io.FileOutputStream.<init>(FileOutputStream.java:236)
       at java.io.FileOutputStream.<init>(FileOutputStream.java:186)
       at androidx.datastore.core.SingleProcessDataStore.writeData$datastore_core(SingleProcessDataStore.kt:425)
       at androidx.datastore.core.SingleProcessDataStore.transformAndWrite(SingleProcessDataStore.kt:410)
       at androidx.datastore.core.SingleProcessDataStore.access$getFile(SingleProcessDataStore.kt:76)
       at androidx.datastore.core.SingleProcessDataStore.access$transformAndWrite(SingleProcessDataStore.kt:76)
       at androidx.datastore.core.SingleProcessDataStore$transformAndWrite$1.invokeSuspend(SingleProcessDataStore.kt:13)
       at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
       at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108)
       at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:115)
       at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:103)
       at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:793)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:697)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:684)

Caused by android.system.ErrnoException
open failed: ENOSPC (No space left on device)

Caused by android.system.ErrnoException: open failed: ENOSPC (No space left on device)
       at libcore.io.Linux.open(Linux.java)
       at libcore.io.ForwardingOs.open(ForwardingOs.java:166)
       at libcore.io.BlockGuardOs.open(BlockGuardOs.java:254)
       at libcore.io.ForwardingOs.open(ForwardingOs.java:166)
       at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:7980)
       at libcore.io.IoBridge.open(IoBridge.java:478)
       at java.io.FileOutputStream.<init>(FileOutputStream.java:236)
       at java.io.FileOutputStream.<init>(FileOutputStream.java:186)
       at androidx.datastore.core.SingleProcessDataStore.writeData$datastore_core(SingleProcessDataStore.kt:425)
       at androidx.datastore.core.SingleProcessDataStore.transformAndWrite(SingleProcessDataStore.kt:410)
       at androidx.datastore.core.SingleProcessDataStore.access$getFile(SingleProcessDataStore.kt:76)
       at androidx.datastore.core.SingleProcessDataStore.access$transformAndWrite(SingleProcessDataStore.kt:76)
       at androidx.datastore.core.SingleProcessDataStore$transformAndWrite$1.invokeSuspend(SingleProcessDataStore.kt:13)
       at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
       at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108)
       at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:115)
       at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:103)
       at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:793)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:697)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:684)

Most likely the error occurs when accessing dataStore without catching FileNotFoundException.

@argzdev
Copy link
Contributor

argzdev commented Apr 4, 2024

Hey @mrblrrd, thanks for pointing me in the right direction. I was able to kind of simulate the behavior using a datastore separately without Firebase and then testing it on a emulator with full memory. It's technically the same with the issue here. I might have a solution in mind. I'll reach out to our engineers and see if we can add this fix.

Notes:

private val Context.dataStore: DataStore<Preferences> by
preferencesDataStore(
name = SessionDataStoreConfigs.SESSIONS_CONFIG_NAME,
corruptionHandler =
ReplaceFileCorruptionHandler { ex ->
Log.w(TAG, "CorruptionException in sessions DataStore in ${getProcessName()}.", ex)
emptyPreferences()
},
)
}

Upon testing, initialization of datastore does not cause any crash. I'm suspecting because the created File() from datastore is being stored as cache in the RAM and not in the internal storage, as a result, even if the internal storage is full, the app would not crash.

On the other hand, when calling the edit from the datastore, this will now write in the internal storage.

context.dataStore.edit { preferences ->
preferences[FirebaseSessionDataKeys.SESSION_ID] = sessionId
}

which will cause the java.io.FileNotFoundException: open failed: ENOSPC failure.

Possible solution would to be add a conditional checker before writing in the datastore, or actually I think a simple try catch would also work.

fun hasEnoughStorage(context: Context): Boolean {
        val stat = context.applicationContext.filesDir.usableSpace
        val threshold =  1L * 1024 * 1024
        Log.d(TAG, "hasEnoughStorage: $stat > $threshold")
        return stat > threshold
}

davidmotson pushed a commit that referenced this issue Apr 17, 2024
Proposed fix for issue #5802. Datastore crashes when writing from a
device that has full internal memory.

I did a manual test by creating a clean project and importing the part
of the code with the condition checkers to simulate the issue. I was
able to receive the issue stacktrace the developer was encountering and
was able to verify that the try catch condition mitigates the issue.
@mrober
Copy link
Contributor

mrober commented May 28, 2024

This was fixed, please update to the latest version.

@mrober mrober closed this as completed May 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants