Skip to content

Fix Firebase fetch() KDoc to document CancellationException#154

Open
kirich1409 wants to merge 1 commit intomainfrom
fix/firebase-fetch-exception
Open

Fix Firebase fetch() KDoc to document CancellationException#154
kirich1409 wants to merge 1 commit intomainfrom
fix/firebase-fetch-exception

Conversation

@kirich1409
Copy link
Copy Markdown
Contributor

Summary

  • Update KDoc on FirebaseConfigValueProvider.fetch() to accurately describe exception behavior
  • Document that CancellationException is propagated without wrapping
  • Document that all other exceptions (including RuntimeException) are wrapped in FetchException

The catch block was already fixed in a prior commit to rethrow CancellationException instead of RuntimeException, but the KDoc was not updated to reflect the new semantics.

Test plan

  • Verify KDoc renders correctly in IDE
  • No code changes — documentation only

🤖 Generated with Claude Code

The catch block was updated to rethrow CancellationException (instead of
RuntimeException) in a prior commit, but the KDoc still described the old
behavior. Update the @throws documentation to reflect the actual semantics.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 10, 2026 11:55
@qodo-code-review
Copy link
Copy Markdown

Review Summary by Qodo

Document CancellationException behavior in Firebase fetch() KDoc

📝 Documentation

Grey Divider

Walkthroughs

Description
• Update KDoc to document CancellationException propagation behavior
• Clarify that FetchException wraps all non-cancellation exceptions
• Document that RuntimeException from await() is wrapped in FetchException
• Specify that CancellationException is propagated without wrapping
Diagram
flowchart LR
  A["fetch() method"] --> B["Firebase operation"]
  B --> C{"Exception type?"}
  C -->|"CancellationException"| D["Propagate directly"]
  C -->|"Other exceptions"| E["Wrap in FetchException"]
  D --> F["Updated KDoc"]
  E --> F
Loading

Grey Divider

File Changes

1. providers/firebase/src/main/kotlin/dev/androidbroadcast/featured/firebase/FirebaseConfigValueProvider.kt 📝 Documentation +7/-3

Enhance fetch() KDoc exception documentation

• Enhanced @throws documentation to clarify FetchException wraps all non-cancellation exceptions
• Added explicit mention that RuntimeException from kotlinx.coroutines.tasks.await() is wrapped
• Added new @throws clause documenting CancellationException propagation without wrapping
• Improved clarity on exception handling semantics and diagnostics

providers/firebase/src/main/kotlin/dev/androidbroadcast/featured/firebase/FirebaseConfigValueProvider.kt


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Copy Markdown

qodo-code-review bot commented Apr 10, 2026

Code Review by Qodo

🐞 Bugs (1)   📘 Rule violations (0)   📎 Requirement gaps (0)   🎨 UX Issues (0)
🐞\ ≡ Correctness (1)

Grey Divider


Remediation recommended

1. Overbroad exception KDoc 🐞
Description
FirebaseConfigValueProvider.fetch() KDoc claims failures are wrapped in FetchException "for any
reason" / "all non-cancellation exceptions", but the implementation only wraps Exception and will
not wrap non-Exception Throwables (e.g., Error). This can mislead callers about what is
guaranteed to be wrapped versus propagated.
Code

providers/firebase/src/main/kotlin/dev/androidbroadcast/featured/firebase/FirebaseConfigValueProvider.kt[R89-95]

+     * @throws FetchException if the Firebase fetch operation fails for any reason, including
+     *   network errors, timeouts, or service unavailability. This wraps all non-cancellation
+     *   exceptions — including [RuntimeException] thrown by [kotlinx.coroutines.tasks.await]
+     *   on Firebase task failure. The [FetchException.cause] holds the original exception for
+     *   diagnostics. See [FetchException] for retry recommendations.
+     * @throws kotlinx.coroutines.CancellationException if the coroutine is cancelled while
+     *   the fetch is in progress; propagated without wrapping.
Evidence
The updated KDoc states that fetch failures are wrapped broadly ("for any reason" / "wraps all
non-cancellation exceptions"), but the implementation rethrows CancellationException and only
wraps Exception in FetchException; it does not catch Throwable, so some non-cancellation
failures can still propagate unwrapped.

providers/firebase/src/main/kotlin/dev/androidbroadcast/featured/firebase/FirebaseConfigValueProvider.kt[84-110]
providers/firebase/src/main/kotlin/dev/androidbroadcast/featured/firebase/FirebaseConfigValueProvider.kt[104-110]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`FirebaseConfigValueProvider.fetch()` KDoc currently over-promises by saying failures are wrapped in `FetchException` "for any reason" / "all non-cancellation exceptions". The implementation only wraps `Exception` (and explicitly rethrows `CancellationException`), so the documented guarantee should be narrowed to match.

### Issue Context
This PR is documentation-only; the safest fix is to adjust KDoc wording (rather than changing runtime behavior to catch `Throwable`).

### Fix Focus Areas
- providers/firebase/src/main/kotlin/dev/androidbroadcast/featured/firebase/FirebaseConfigValueProvider.kt[84-96]

### Suggested change
Reword to something like:
- `@throws FetchException` if the Firebase task completes exceptionally with a non-cancellation **Exception** (original stored in `cause`).
- Keep `@throws CancellationException` as-is.
- Avoid implying `await` specifically throws `RuntimeException`; instead say it wraps any exception thrown by `await`/task failure.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Updates Firebase provider documentation to match the current fetch() exception semantics (propagating coroutine cancellation while wrapping other failures in FetchException).

Changes:

  • Refines FirebaseConfigValueProvider.fetch() KDoc to explicitly document CancellationException propagation.
  • Clarifies that other non-cancellation failures are wrapped in FetchException and preserved as cause.

Comment on lines +89 to +93
* @throws FetchException if the Firebase fetch operation fails for any reason, including
* network errors, timeouts, or service unavailability. This wraps all non-cancellation
* exceptions — including [RuntimeException] thrown by [kotlinx.coroutines.tasks.await]
* on Firebase task failure. The [FetchException.cause] holds the original exception for
* diagnostics. See [FetchException] for retry recommendations.
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

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

KDoc says the fetch operation fails "for any reason" but the implementation only wraps non-cancellation Exceptions (and will still let non-Exception Throwables like Error propagate). Consider tightening the wording to match the actual behavior: wraps all non-cancellation exceptions thrown by await() / Firebase APIs.

Suggested change
* @throws FetchException if the Firebase fetch operation fails for any reason, including
* network errors, timeouts, or service unavailability. This wraps all non-cancellation
* exceptions — including [RuntimeException] thrown by [kotlinx.coroutines.tasks.await]
* on Firebase task failure. The [FetchException.cause] holds the original exception for
* diagnostics. See [FetchException] for retry recommendations.
* @throws FetchException if [kotlinx.coroutines.tasks.await] or the underlying Firebase
* Remote Config APIs throw a non-cancellation [Exception] while fetching, including
* errors such as network failures, timeouts, or service unavailability. The
* [FetchException.cause] holds the original exception for diagnostics. See
* [FetchException] for retry recommendations.

Copilot uses AI. Check for mistakes.
* exceptions — including [RuntimeException] thrown by [kotlinx.coroutines.tasks.await]
* on Firebase task failure. The [FetchException.cause] holds the original exception for
* diagnostics. See [FetchException] for retry recommendations.
* @throws kotlinx.coroutines.CancellationException if the coroutine is cancelled while
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

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

For consistency with the rest of the file (e.g., @throws IllegalStateException above) and to avoid redundancy with the existing import, consider using CancellationException instead of the fully-qualified kotlinx.coroutines.CancellationException in the @throws tag.

Suggested change
* @throws kotlinx.coroutines.CancellationException if the coroutine is cancelled while
* @throws CancellationException if the coroutine is cancelled while

Copilot uses AI. Check for mistakes.
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.

2 participants