Skip to content

fix: replace bare except with typed exceptions in service.py#7297

Open
harshadkhetpal wants to merge 1 commit intovoxel51:developfrom
harshadkhetpal:fix/bare-except-service
Open

fix: replace bare except with typed exceptions in service.py#7297
harshadkhetpal wants to merge 1 commit intovoxel51:developfrom
harshadkhetpal:fix/bare-except-service

Conversation

@harshadkhetpal
Copy link
Copy Markdown
Contributor

@harshadkhetpal harshadkhetpal commented Apr 2, 2026

Summary

Replace 3 bare except: clauses with typed exceptions in fiftyone/core/service.py.

Bare except: intercepts all exceptions including SystemExit, KeyboardInterrupt, and GeneratorExit, which can suppress critical signals and make services impossible to stop cleanly.

Changes:

# Lines 252 & 262 — reraise pattern: bare except → BaseException
# Before
    except:
        raise PermissionError(...)

# After
    except BaseException:
        raise PermissionError(...)

# Line 317 — swallow non-fatal: bare except → Exception
# Before
    except:
        server_version = None

# After
    except Exception:
        server_version = None

Testing

No behavior change — correctness/style fix only. Reraise blocks preserve the same semantics; the swallow block now correctly allows KeyboardInterrupt to propagate.

Summary by CodeRabbit

  • Refactor
    • Improved internal exception handling logic for increased robustness and consistency.

Bare `except:` clauses catch SystemExit and KeyboardInterrupt, masking
critical signals. Fixed 3 occurrences:
- Lines 252, 262: bare reraise pattern → except BaseException:
- Line 317: swallow non-fatal error → except Exception:
@harshadkhetpal harshadkhetpal requested a review from a team as a code owner April 2, 2026 21:59
@voxel51-bot
Copy link
Copy Markdown
Collaborator

Thanks for opening this pull request, @harshadkhetpal! 🎉

A maintainer will review your changes soon. In the meantime, please ensure:

  • You filled out the PR template above, completely to the best of your knowledge
  • You include tests (if applicable)
  • You read the contribution guide

Helpful resources:

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 2, 2026

Walkthrough

The pull request modifies exception handling in fiftyone/core/service.py across two service methods. In DatabaseService.command, filesystem setup operations now explicitly catch BaseException instead of using a bare except: clause. In ServerService.start, the HTTP request version extraction handler is narrowed to catch Exception explicitly instead of catching all exceptions. These changes alter which throwable types are handled locally versus propagated upstream.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description covers the changes and rationale but is missing the required template structure including Related Issues, Testing section, and Release Notes. Fill out the complete PR template: add a Related Issues section, expand the Testing section with test details or rationale, and specify Release Notes impact.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: replacing bare except clauses with typed exceptions in service.py.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@fiftyone/core/service.py`:
- Around line 250-255: Replace the broad BaseException handlers around
etau.ensure_dir(database_dir) (and the similar block at lines 257-265) with a
specific filesystem exception catch (e.g., except OSError as e) and re-raise
PermissionError chaining the original exception (raise PermissionError("Database
directory `%s` cannot be written to" % database_dir) from e) so shutdown signals
like KeyboardInterrupt/SystemExit are not masked and the original cause is
preserved; locate the try/except blocks in fiftyone.core.service around
etau.ensure_dir to apply this change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 5bea6690-3285-4174-87cd-171e60e3133f

📥 Commits

Reviewing files that changed from the base of the PR and between bd3db37 and ea917e9.

📒 Files selected for processing (1)
  • fiftyone/core/service.py

Comment on lines 250 to 255
try:
etau.ensure_dir(database_dir)
except:
except BaseException:
raise PermissionError(
"Database directory `%s` cannot be written to" % database_dir
)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verifies the Python exception boundary this change relies on.
python - <<'PY'
try:
    raise KeyboardInterrupt()
except BaseException:
    print("BaseException catches KeyboardInterrupt")

try:
    raise KeyboardInterrupt()
except Exception:
    print("Exception catches KeyboardInterrupt")
except BaseException:
    print("Exception lets KeyboardInterrupt propagate past Exception")
PY

Repository: voxel51/fiftyone

Length of output: 157


🏁 Script executed:

# Read the relevant section of fiftyone/core/service.py
head -270 /dev/null 2>/dev/null || echo "checking file path"
find . -name "service.py" -path "*/fiftyone/core/*" -type f | head -5

Repository: voxel51/fiftyone

Length of output: 86


🏁 Script executed:

# Check if the file exists and read the relevant lines
if [ -f "fiftyone/core/service.py" ]; then
  echo "=== Lines 240-270 ===" 
  sed -n '240,270p' fiftyone/core/service.py
else
  echo "File not found, searching for it"
  find . -name "service.py" -type f
fi

Repository: voxel51/fiftyone

Length of output: 968


🏁 Script executed:

# Search for etau module and ensure_dir/ensure_basedir/ensure_empty_file definitions
rg -A 10 "def ensure_dir|def ensure_basedir|def ensure_empty_file" --type python

Repository: voxel51/fiftyone

Length of output: 90


🏁 Script executed:

# Search for etau module and ensure_* functions
rg "def ensure_dir|def ensure_basedir|def ensure_empty_file" --glob "*.py" | head -20

Repository: voxel51/fiftyone

Length of output: 160


🏁 Script executed:

# Find where etau is imported from
rg "import.*etau|from.*etau" fiftyone/core/service.py

Repository: voxel51/fiftyone

Length of output: 89


🏁 Script executed:

# Check what exceptions etau functions can raise
rg -A 15 "def ensure_dir" --glob "*.py" | head -40

Repository: voxel51/fiftyone

Length of output: 763


🏁 Script executed:

# Search for eta.core.utils usage and exception patterns in the codebase
rg "etau\." fiftyone/core/service.py -B 2 -A 5 | head -50

Repository: voxel51/fiftyone

Length of output: 742


🏁 Script executed:

# Check if eta is a dependency and what version
cat setup.py pyproject.toml requirements.txt 2>/dev/null | grep -i eta

Repository: voxel51/fiftyone

Length of output: 269


🏁 Script executed:

# Search for other exception handling patterns around filesystem operations in the codebase
rg "ensure_dir|ensure_basedir|ensure_empty_file" -B 3 -A 3 --glob "*.py" | head -80

Repository: voxel51/fiftyone

Length of output: 4128


🏁 Script executed:

# Try to find eta package documentation or source in the repo
find . -name "*eta*" -type d | head -10

Repository: voxel51/fiftyone

Length of output: 125


🏁 Script executed:

# Check for any try-except blocks around etau.ensure_* calls to see what exceptions are expected
rg -B 2 -A 5 "etau\.(ensure_dir|ensure_basedir|ensure_empty_file)" --glob "*.py" | grep -A 5 "except"

Repository: voxel51/fiftyone

Length of output: 664


🏁 Script executed:

# Look for test cases that might show what exceptions are expected
rg "ensure_dir|ensure_basedir|ensure_empty_file" tests/ -A 3 -B 3 --glob "*.py" | head -60

Repository: voxel51/fiftyone

Length of output: 1003


🏁 Script executed:

# Check eta package version and see if there's any documentation about exceptions
cat package/voxel51-eta/setup.py 2>/dev/null | head -50

Repository: voxel51/fiftyone

Length of output: 42


🏁 Script executed:

# Search for any error handling documentation or patterns in the eta directory
find ./package/voxel51-eta -name "*.py" -type f 2>/dev/null | head -5

Repository: voxel51/fiftyone

Length of output: 42


🏁 Script executed:

# Look for what exceptions filesystem operations typically raise
python3 << 'EOF'
import os
try:
    # Simulate permission error
    os.makedirs("/root/test_perm", exist_ok=True)
except Exception as e:
    print(f"Type: {type(e).__name__}, bases: {type(e).__bases__}")

# Check OSError hierarchy
print(f"\nOSError subclasses include:")
for exc in [FileNotFoundError, PermissionError, IsADirectoryError]:
    print(f"  {exc.__name__}: {issubclass(exc, OSError)}")
EOF

Repository: voxel51/fiftyone

Length of output: 215


🏁 Script executed:

# Check if we can find eta source code in the package directory
find ./package/voxel51-eta -name "utils.py" -o -name "core.py" 2>/dev/null | head -10

Repository: voxel51/fiftyone

Length of output: 42


🏁 Script executed:

# Look at the entire structure of the eta package
ls -la ./package/voxel51-eta/ 2>/dev/null

Repository: voxel51/fiftyone

Length of output: 226


🏁 Script executed:

# Search for ensure_dir implementation in eta if available
rg "def ensure_dir" ./package/voxel51-eta --glob "*.py" 2>/dev/null || echo "Not found in eta package, it's likely an external dependency"

Repository: voxel51/fiftyone

Length of output: 120


🏁 Script executed:

# Since eta is external, check if there's any documentation comment or exception specification in fiftyone storage.py
sed -n '1,50p' fiftyone/core/storage.py | head -30

Repository: voxel51/fiftyone

Length of output: 539


BaseException still masks shutdown signals.

Lines 252 and 262 catch BaseException, which includes KeyboardInterrupt, SystemExit, and GeneratorExit. These signals will be rewritten as PermissionError, preventing clean shutdown. Catch the concrete filesystem exceptions from etau.ensure_* instead and preserve the original cause.

Suggested fix:

Exception handling changes
         try:
             etau.ensure_dir(database_dir)
-        except BaseException:
+        except OSError as e:
             raise PermissionError(
                 "Database directory `%s` cannot be written to" % database_dir
-            )
+            ) from e

         try:
             etau.ensure_basedir(log_path)

             if not os.path.isfile(log_path):
                 etau.ensure_empty_file(log_path)
-        except BaseException:
+        except OSError as e:
             raise PermissionError(
                 "Database log path `%s` cannot be written to" % log_path
-            )
+            ) from e

Also applies to: 257-265

🧰 Tools
🪛 Ruff (0.15.7)

[warning] 252-252: Do not catch blind exception: BaseException

(BLE001)


[warning] 253-255: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


[warning] 254-254: Use format specifiers instead of percent format

Replace with format specifiers

(UP031)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@fiftyone/core/service.py` around lines 250 - 255, Replace the broad
BaseException handlers around etau.ensure_dir(database_dir) (and the similar
block at lines 257-265) with a specific filesystem exception catch (e.g., except
OSError as e) and re-raise PermissionError chaining the original exception
(raise PermissionError("Database directory `%s` cannot be written to" %
database_dir) from e) so shutdown signals like KeyboardInterrupt/SystemExit are
not masked and the original cause is preserved; locate the try/except blocks in
fiftyone.core.service around etau.ensure_dir to apply this change.

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