Improve error message when database directory is not writable#6294
Improve error message when database directory is not writable#6294VedantMadane wants to merge 9 commits intobeetbox:masterfrom
Conversation
|
Thank you for the PR! The changelog has not been updated, so here is a friendly reminder to check if you need to add an entry. |
There was a problem hiding this comment.
Hey - I've found 2 issues, and left some high level feedback:
- The special-case
readonly/unable to openbranch currently assumes a directory permissions issue; consider broadening the message to mention both file and directory permissions (or phrasing it more generically) since these errors can also arise from file-level ACLs or missing paths. - When constructing
db_dir = os.path.dirname(dbpath), it may be safer to normalize the path (e.g., viaos.path.abspath) and handle the case wheredbpathhas no directory component, so that the resulting message about the directory being writable is always meaningful.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The special-case `readonly`/`unable to open` branch currently assumes a directory permissions issue; consider broadening the message to mention both file and directory permissions (or phrasing it more generically) since these errors can also arise from file-level ACLs or missing paths.
- When constructing `db_dir = os.path.dirname(dbpath)`, it may be safer to normalize the path (e.g., via `os.path.abspath`) and handle the case where `dbpath` has no directory component, so that the resulting message about the directory being writable is always meaningful.
## Individual Comments
### Comment 1
<location> `beets/ui/__init__.py:1513-1518` </location>
<code_context>
+ # Check for permission-related errors and provide a helpful message
+ error_str = str(db_error).lower()
+ dbpath_display = util.displayable_path(dbpath)
+ if "readonly" in error_str or "unable to open" in error_str:
+ db_dir = os.path.dirname(dbpath)
+ raise UserError(
+ f"database file {dbpath_display} could not be opened due to a "
+ f"permissions error. Please check that the directory "
+ f"{util.displayable_path(db_dir)} is writable."
+ )
raise UserError(
</code_context>
<issue_to_address>
**issue (bug_risk):** The permission-specific branch may misdiagnose non-permission errors as permission issues.
Relying on the generic substring `"unable to open"` and mapping it directly to a permissions error is brittle. This message can also arise from non-permission issues (missing directory, malformed path, unavailable filesystem). Please either narrow the pattern to permission-specific cases, include the original `db_error` in the message for context, or soften the wording so it doesn’t claim permissions are the only cause.
</issue_to_address>
### Comment 2
<location> `beets/ui/__init__.py:1512-1522` </location>
<code_context>
+ dbpath_display = util.displayable_path(dbpath)
+ if "readonly" in error_str or "unable to open" in error_str:
+ db_dir = os.path.dirname(dbpath)
+ raise UserError(
+ f"database file {dbpath_display} could not be opened due to a "
+ f"permissions error. Please check that the directory "
+ f"{util.displayable_path(db_dir)} is writable."
+ )
raise UserError(
</code_context>
<issue_to_address>
**suggestion:** The permission-focused message drops the original SQLite error details, reducing debuggability.
In this branch, the original `db_error` isn’t surfaced, unlike in the generic error path. Please include it here as well (e.g., by appending `f" (original error: {db_error})"`) so callers retain the underlying SQLite details for troubleshooting.
```suggestion
dbpath_display = util.displayable_path(dbpath)
if "readonly" in error_str or "unable to open" in error_str:
db_dir = os.path.dirname(dbpath)
raise UserError(
f"database file {dbpath_display} could not be opened due to a "
f"permissions error. Please check that the directory "
f"{util.displayable_path(db_dir)} is writable "
f"(original error: {db_error})."
)
raise UserError(
f"database file {dbpath_display} could not be opened: {db_error}"
)
```
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #6294 +/- ##
=======================================
Coverage 68.97% 68.97%
=======================================
Files 140 140
Lines 18694 18702 +8
Branches 3060 3062 +2
=======================================
+ Hits 12894 12900 +6
- Misses 5153 5154 +1
- Partials 647 648 +1
🚀 New features to boost your workflow:
|
|
readonly errors only occur on write operations, not during database open. I've pushed a fix that removes the Also refined the error message to be more specific about the directory-not-writable-on-create scenario. |
Resolved conflict in docs/changelog.rst by keeping both bug fix entries: - Database permission error message improvement (PR beetbox#6294) - ArtResizer OSError handling (from master)
Add specific error handling for permission-related SQLite errors. When the error message contains 'readonly' or 'unable to open', provide a helpful message suggesting the user check directory permissions. Also fix the typo 'cannot not' to 'could not'. Closes beetbox#1676
- Changed wording from asserting permission error to suggesting it may be a permissions issue - Include original db_error in the error message for debuggability - Mention both file and directory in the error message
Add entry to changelog documenting improved error message when database directory is not writable. The fix provides clearer guidance to users when SQLite fails to open the database due to permission issues. Closes beetbox#1676 Addresses review feedback requesting changelog update. # Conflicts: # docs/changelog.rst
Add tests for both database error paths: - Test 'unable to open' error path with directory permission message - Test fallback error path for other database errors This addresses the code coverage gap identified in PR review, ensuring both error branches are covered by tests.
# Conflicts: # docs/changelog.rst
f1fa526 to
29b4ee3
Compare
|
Maybe it'd be worth addressing this error message as part of this PR as well? This happens whenever you try to write to the database while it is already being written. You can re-produce it by opening two terminal windows:
|
Adds better error handling for SQLite OperationalError when the database file or directory is not writable. When the error message contains 'readonly' or 'unable to open', provides a helpful message suggesting the user check directory permissions. Also fixes a typo in the error message ('cannot not' to 'could not'). Closes #1676