Android
EACCES
Permission Denied
Open Failed
Error Handling

Exception 'open failed EACCES Permission denied' on Android

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

open failed: EACCES (Permission denied) on Android means your app tried to access a file path it is not allowed to read or write. The fix is usually not just adding one manifest permission. You need to align path choice, runtime permissions, and Android storage model behavior.

Why the Error Happens

This exception appears when file APIs call into Linux-level path access that is blocked by app sandbox rules or storage policies. Common causes include:

  • writing outside app-scoped directories
  • missing runtime permission grant
  • using direct file paths where content URIs are required
  • trying to read external paths without Storage Access Framework flow

A reliable fix starts by identifying which path is being opened.

Use App-Scoped Storage First

The safest default is app-specific directories, which usually do not need broad storage permissions.

kotlin
1val file = File(context.filesDir, "session.json")
2file.writeText("ok")
3
4val cacheFile = File(context.cacheDir, "tmp.txt")
5cacheFile.writeText("cached")

For media-like output on modern Android, prefer MediaStore APIs instead of raw external paths.

Request Runtime Permissions Correctly

If you truly need protected storage access on older API levels, request runtime permissions and check grant results.

kotlin
1private val permissionLauncher =
2    registerForActivityResult(ActivityResultContracts.RequestPermission()) { granted ->
3        if (granted) {
4            readExternalData()
5        } else {
6            showPermissionDeniedMessage()
7        }
8    }
9
10fun ensureReadPermission() {
11    permissionLauncher.launch(Manifest.permission.READ_EXTERNAL_STORAGE)
12}

Do not attempt file operations before grant callback success.

Prefer content URIs over Raw Paths

When users pick files through system picker, use returned Uri and ContentResolver instead of converting to filesystem paths.

kotlin
1fun readFromUri(context: Context, uri: Uri): String {
2    context.contentResolver.openInputStream(uri).use { input ->
3        requireNotNull(input) { "Cannot open URI stream" }
4        return input.bufferedReader().readText()
5    }
6}

This approach respects storage provider boundaries and avoids many permission-denied errors.

Writing Shared Media with MediaStore

For shared downloads, images, or videos, insert through MediaStore APIs so Android grants correct access.

kotlin
1val values = ContentValues().apply {
2    put(MediaStore.Downloads.DISPLAY_NAME, "report.txt")
3    put(MediaStore.Downloads.MIME_TYPE, "text/plain")
4}
5
6val uri = context.contentResolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, values)
7requireNotNull(uri)
8
9context.contentResolver.openOutputStream(uri).use { out ->
10    requireNotNull(out)
11    out.write("hello".toByteArray())
12}

This pattern is safer than attempting direct file writes to public directories.

API-Level Permission Notes

Permission names changed across Android versions for media access. On recent versions, media-specific permissions are used instead of broad storage reads. Keep permission checks centralized by API level so screens do not duplicate logic and drift over time.

This also helps QA validate permission prompts and fallback flows consistently.

Scoped Storage and API-Level Strategy

Android 10 and later enforce scoped storage behavior. Direct path access patterns that worked on older devices may fail. Keep logic version-aware only when necessary, and centralize it in one storage helper module.

For shared documents, Storage Access Framework with persisted URI permissions is often the correct long-term design.

Debugging Checklist

When reproducing an EACCES issue, capture:

  • exact path or URI attempted
  • API level and target SDK
  • current permission state at runtime
  • whether operation is read, write, or delete

Log these values before open calls. Most permission issues become obvious once you inspect concrete runtime context.

Common Pitfalls

  • Adding manifest permissions but not requesting them at runtime on supported API levels.
  • Accessing shared storage with hardcoded paths instead of using proper system providers.
  • Assuming behavior on older Android versions matches modern scoped storage rules.
  • Attempting file access from background components without available context or permission flow.
  • Catching and suppressing IOException without logging path and permission state.

Summary

  • EACCES indicates blocked file access under Android sandbox or storage policy.
  • Prefer app-scoped directories and content URIs to minimize permission complexity.
  • Request runtime permissions before performing sensitive file operations.
  • Use MediaStore and Storage Access Framework for shared storage scenarios.
  • Debug with concrete path, API level, and permission-state logs.

Course illustration
Course illustration

All Rights Reserved.