Skip to content

Crash: FileNotFoundException EACCES in Uri.fileContent when reading content URI (#4426)#4435

Merged
johnnyluo merged 4 commits into
mainfrom
agent/4426-crash--filenotfoundexception-eacces-in-u
May 8, 2026
Merged

Crash: FileNotFoundException EACCES in Uri.fileContent when reading content URI (#4426)#4435
johnnyluo merged 4 commits into
mainfrom
agent/4426-crash--filenotfoundexception-eacces-in-u

Conversation

@Vaulty-bot
Copy link
Copy Markdown
Collaborator

@Vaulty-bot Vaulty-bot commented May 7, 2026

Fixes #4426

Changes

  • FileHelper.kt: Wrap Uri.fileContent body in try/catch, using .use {} for the InputStream. Transient permission failures (FileNotFoundException with EACCES) and other I/O exceptions now log via Timber and return null instead of propagating and crashing the app.

Checklist

  • Lint clean (ktfmt passes; ./gradlew lint could not run in this environment due to a 401 fetching com.trustwallet:wallet-core from GitHub Maven — needs CI run)
  • Build verified (S1)
  • Self-reviewed against requirements (S3)
  • No secrets committed
  • Conventional commit messages

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Improved file import validation with clearer error messaging when unsupported files are loaded.
    • Enhanced error handling to gracefully manage file content failures and prevent processing of invalid files.
  • Tests

    • Added comprehensive test coverage for file loading and error scenarios.

Wrap contentResolver.openInputStream() in try/catch so transient EACCES
or other I/O failures return null instead of crashing the app. Also use
.use {} to ensure the InputStream is closed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 7, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds exception handling to Uri.fileContent() to gracefully handle I/O failures by returning null, then updates the ViewModel to detect and surface an unsupported-file error when file content cannot be loaded. New test suites cover all failure paths and cancellation behavior across both layers.

Changes

File URI Exception Handling and ViewModel Validation

Layer / File(s) Summary
Core Exception Handling
data/src/main/kotlin/com/vultisig/wallet/data/common/FileHelper.kt
Uri.fileContent() now wraps I/O operations in try/catch, rethrowing CancellationException and logging/returning null for FileNotFoundException, SecurityException, and IOException.
FileHelper Test Coverage
data/src/test/kotlin/com/vultisig/wallet/data/common/FileHelperUriFileContentTest.kt
Test suite validates success case and failure paths: EACCES FileNotFoundException, generic FileNotFoundException, SecurityException, IOException, null stream, and verifies CancellationException propagates.
ViewModel File Content Validation
app/src/main/java/com/vultisig/wallet/ui/models/ImportFileViewModel.kt
saveFileToAppDir() now checks if uri.fileContent(context) is null; clears file state fields and sets an "import file not supported" error, exiting before parsing.
ViewModel Test Coverage
app/src/test/java/com/vultisig/wallet/ui/models/ImportFileViewModelTest.kt
New test verifies that when file content is null, the ViewModel sets the not-supported error, clears UI state, and skips parsing.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

A humble file seeks to be read,
but streams may fall or permissions dread.
Now softly caught, a null returned with care—
the ViewModel knows to flag the error there. 🐰✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly references the crash issue from #4426 and accurately describes the main change: handling FileNotFoundException EACCES in Uri.fileContent.
Linked Issues check ✅ Passed All coding requirements from #4426 are met: exception handling in Uri.fileContent catches FileNotFoundException and returns null; pattern consistency with saveContentToUri; CancellationException properly rethrown; ImportFileViewModel surfaces UI error; comprehensive unit tests added.
Out of Scope Changes check ✅ Passed All changes are directly scoped to #4426: FileHelper.kt fixes EACCES handling, ImportFileViewModel surfaces the error properly, and corresponding tests validate the implementations. No unrelated changes detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch agent/4426-crash--filenotfoundexception-eacces-in-u

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Vaulty-bot
Copy link
Copy Markdown
Collaborator Author

Pushed updated implementation.

@aminsato
Copy link
Copy Markdown
Collaborator

aminsato commented May 7, 2026

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 7, 2026

✅ Actions performed

Full review triggered.

@Vaulty-bot
Copy link
Copy Markdown
Collaborator Author

No actionable changes made.

The only feedback comment is @coderabbitai full review from @aminsato, which is a directive to the CodeRabbit bot rather than feedback addressed to me. CodeRabbit has acknowledged the request ("Full review triggered.") but has not yet posted any findings on this PR — it was rate-limited on its initial pass and the full review run hasn't returned results yet.

There are currently no inline review comments and no formal review verdicts to address. I'll wait for CodeRabbit's findings (or human reviewer feedback) before making further changes. If you'd like me to act on something specific in the meantime, please point me at it.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 7, 2026

Tip

For best results, initiate chat on the files or code changes.

@Vaulty-bot Thanks for the update! That makes sense — I'll kick off the full review now so my findings are posted and you have concrete feedback to work from.

[full_review]

Copy link
Copy Markdown
Collaborator

@rkokhatskyi rkokhatskyi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Vaulty-bot please cover this case by Unit tests

Comment thread data/src/main/kotlin/com/vultisig/wallet/data/common/FileHelper.kt
Comment thread data/src/main/kotlin/com/vultisig/wallet/data/common/FileHelper.kt
Vaulty-bot and others added 2 commits May 7, 2026 20:43
Add unit tests verifying that Uri.fileContent returns null instead of
crashing when the platform throws FileNotFoundException (EACCES),
SecurityException, generic IOException during read, or returns a null
InputStream — covering the crash scenario from issue #4426.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Uri.fileContent now rethrows CancellationException so a cancelled
  viewModelScope no longer keeps executing through the caller.
- ImportFileViewModel.saveFileToAppDir surfaces the unsupported-file
  error UiText when fileContent returns null, matching the existing
  fetchFileName error path for the same EACCES root cause.
- Add unit tests for both behaviors.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Vaulty-bot
Copy link
Copy Markdown
Collaborator Author

Addressed review feedback in commits b59ad1a and 3e5b842.

Formal review (rkokhatskyi, CHANGES_REQUESTED — "please cover this case by Unit tests"):

  • b59ad1a — Added FileHelperUriFileContentTest covering the error paths for Uri.fileContent:
    • Returns content on successful read
    • Returns null on FileNotFoundException with EACCES (the original crash from Crash: FileNotFoundException EACCES in Uri.fileContent when reading content URI #4426)
    • Returns null on generic FileNotFoundException
    • Returns null on SecurityException
    • Returns null when the InputStream throws IOException mid-read
    • Returns null when openInputStream returns null
    • Does not swallow CancellationException (added in 3e5b842 alongside the rethrow)

Inline review comments:

  • #discussion_r3204564773 — catch (e: Exception) swallowing CancellationException: fixed in 3e5b842 by adding catch (e: CancellationException) { throw e } before the generic Exception catch.
  • #discussion_r3204564783 — silent no-op in ImportFileViewModel.saveFileToAppDir when fileContent returns null: fixed in 3e5b842 by surfacing R.string.import_file_not_supported as error UiText and clearing fileUri/fileName/fileContent/isZip, mirroring the existing fetchFileName error path. Covered by a new ImportFileViewModelTest case.

Notes:

  • ./gradlew testDebugUnitTest could not run locally (401 fetching com.trustwallet:wallet-core from GitHub Maven, same constraint noted on the original commit). CI will exercise the new tests.
  • ktfmt clean across all modules.

Copy link
Copy Markdown
Contributor

@johnnyluo johnnyluo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@johnnyluo johnnyluo enabled auto-merge May 7, 2026 22:27
@johnnyluo johnnyluo added this pull request to the merge queue May 7, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks May 7, 2026
@rkokhatskyi
Copy link
Copy Markdown
Collaborator

@Vaulty-bot fix the build errors

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
data/src/main/kotlin/com/vultisig/wallet/data/common/FileHelper.kt (1)

153-156: ⚡ Quick win

Narrow the fallback catch to expected I/O/permission failures.

Catching Exception here may mask unrelated runtime defects. Given the PR goal, prefer explicit catches for FileNotFoundException, SecurityException, and IOException (after CancellationException) and let unexpected exceptions surface.

♻️ Suggested change
-    } catch (e: Exception) {
+    } catch (e: java.io.FileNotFoundException) {
+        Timber.e(e, "error in fileContent")
+        null
+    } catch (e: SecurityException) {
+        Timber.e(e, "error in fileContent")
+        null
+    } catch (e: java.io.IOException) {
         Timber.e(e, "error in fileContent")
         null
     }

Based on learnings: "Do not use a broad catch (catch (Exception)) to swallow errors in Kotlin. Catch specific, actionable exceptions … Avoid masking real failures."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@data/src/main/kotlin/com/vultisig/wallet/data/common/FileHelper.kt` around
lines 153 - 156, In the fileContent function replace the broad catch (e:
Exception) with specific catches: first handle CancellationException by
rethrowing it, then catch FileNotFoundException, SecurityException, and
IOException and log them with Timber.e (preserving the "error in fileContent"
context) returning null as before; do not catch other Exceptions so unexpected
runtime errors propagate.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@data/src/main/kotlin/com/vultisig/wallet/data/common/FileHelper.kt`:
- Around line 153-156: In the fileContent function replace the broad catch (e:
Exception) with specific catches: first handle CancellationException by
rethrowing it, then catch FileNotFoundException, SecurityException, and
IOException and log them with Timber.e (preserving the "error in fileContent"
context) returning null as before; do not catch other Exceptions so unexpected
runtime errors propagate.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7a97bc6e-4f6d-4caf-ba2f-89a93bf2a36b

📥 Commits

Reviewing files that changed from the base of the PR and between 3029e03 and 6d73f89.

📒 Files selected for processing (4)
  • app/src/main/java/com/vultisig/wallet/ui/models/ImportFileViewModel.kt
  • app/src/test/java/com/vultisig/wallet/ui/models/ImportFileViewModelTest.kt
  • data/src/main/kotlin/com/vultisig/wallet/data/common/FileHelper.kt
  • data/src/test/kotlin/com/vultisig/wallet/data/common/FileHelperUriFileContentTest.kt

@Vaulty-bot
Copy link
Copy Markdown
Collaborator Author

Available commands:

Command Description
@Vaulty-bot investigate Analyze the codebase and post a proposed solution (no code changes)
@Vaulty-bot pick up Implement changes on this issue or PR
@Vaulty-bot help Show this message
/agent split Confirm a proposed split and create/refresh sub-issues (sub-issues are NEVER created without this confirmation)
/agent proceed Re-queue a blocked issue for implementation; after a split-confirmation prompt this means "keep as a single issue"
/agent re-investigate Force a fresh investigation
/agent stop Stop agent processing on this issue
fix nitpicks / resolve all comments / no matter of severity Plain-English triggers on a PR that tell the review worker to address every comment, including 🧹 Nitpick items

Agent runs every ~5 minutes. Only trusted org members and collaborators can trigger commands.

@Vaulty-bot
Copy link
Copy Markdown
Collaborator Author

Picked up CodeRabbit feedback (actionable issues only, skipping nitpicks). Working on it.

@Vaulty-bot
Copy link
Copy Markdown
Collaborator Author

Only nitpick feedback remaining on this PR.

CodeRabbit review (id 4248235704) flagged one 🧹 Nitpick: narrow the fallback catch (e: Exception) in FileHelper.kt:153 to explicit FileNotFoundException, SecurityException, and IOException after the CancellationException rethrow. Skipped per the default policy (no action on nitpick-level feedback unless explicitly requested) — happy to address it if you'd like.

Prior actionable comments (rkokhatskyi, id 3204564773 / id 3204564783) were both addressed in 3e5b842 and have inline replies.

CI build-and-test is still in progress at HEAD 6d73f89.

@johnnyluo johnnyluo added this pull request to the merge queue May 7, 2026
Merged via the queue into main with commit 3cc460d May 8, 2026
2 checks passed
@johnnyluo johnnyluo deleted the agent/4426-crash--filenotfoundexception-eacces-in-u branch May 8, 2026 00:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Crash: FileNotFoundException EACCES in Uri.fileContent when reading content URI

4 participants