fix: raise RuntimeError on invalid JSON instead of crashing with NameError#85
Conversation
…Error When a descriptor file contained invalid JSON, the ValueError was caught and logged but descriptor_dict was never assigned. The subsequent `return Descriptor(descriptor_dict, ...)` then raised NameError, which escaped the caller's except clause and crashed the data model manager. Fix: re-raise as RuntimeError so DescriptorsFromDirectory's existing except clause catches it and continues to the next file. Adds three regression tests covering: - invalid JSON raises RuntimeError - directory path raises RuntimeError - invalid file is skipped while valid files still load Closes brighthive#10
📝 WalkthroughWalkthroughError handling in the descriptor loading system is improved by converting JSON decode failures from info logging to explicit Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment Tip CodeRabbit can use your project's `ruff` configuration to improve the quality of Python code reviews.Add a Ruff configuration file to your project to customize how CodeRabbit runs |
There was a problem hiding this comment.
🧹 Nitpick comments (2)
data_resource_api/app/utils/descriptor.py (2)
82-85: Use exception chaining to preserve the original traceback.The static analysis hint is valid. When re-raising as a different exception type, use
fromto chain exceptions and preserve the originalValueErrortraceback for debugging.♻️ Proposed fix
except ValueError: - raise RuntimeError( + except ValueError as e: + raise RuntimeError( f"Failed to load JSON file. JSON is probably invalid in file '{os.path.join(schema_dir, file_name)}'" - ) + ) from e🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@data_resource_api/app/utils/descriptor.py` around lines 82 - 85, The except block that catches ValueError and re-raises a RuntimeError loses the original traceback; capture the original exception (e.g., except ValueError as e:) and re-raise using exception chaining (raise RuntimeError(f"Failed to load JSON file. JSON is probably invalid in file '{os.path.join(schema_dir, file_name)}'") from e) so the original ValueError traceback is preserved; update the except clause in descriptor.py where ValueError is handled to use the as e pattern and the from e chaining.
48-48: Redundant exception types in the except clause.
ValueErrorandRuntimeErrorare both subclasses ofException, so listing them explicitly alongsideExceptionhas no effect. This may have been intentional to document expected exception types, but it could confuse readers.♻️ Proposed simplification
- except (Exception, ValueError, RuntimeError) as e: + except Exception as e:If documenting expected types is desired, a comment would be clearer:
# Catches RuntimeError (invalid JSON, directory as file) and other errors except Exception as e:🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@data_resource_api/app/utils/descriptor.py` at line 48, The except clause in descriptor.py currently lists redundant exception types ("except (Exception, ValueError, RuntimeError) as e"); simplify it to just "except Exception as e" and, if you want to document expected errors, add a brief comment above (e.g., "# catches RuntimeError/ValueError and other exceptions") to make intent clear without repeating subclasses.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@data_resource_api/app/utils/descriptor.py`:
- Around line 82-85: The except block that catches ValueError and re-raises a
RuntimeError loses the original traceback; capture the original exception (e.g.,
except ValueError as e:) and re-raise using exception chaining (raise
RuntimeError(f"Failed to load JSON file. JSON is probably invalid in file
'{os.path.join(schema_dir, file_name)}'") from e) so the original ValueError
traceback is preserved; update the except clause in descriptor.py where
ValueError is handled to use the as e pattern and the from e chaining.
- Line 48: The except clause in descriptor.py currently lists redundant
exception types ("except (Exception, ValueError, RuntimeError) as e"); simplify
it to just "except Exception as e" and, if you want to document expected errors,
add a brief comment above (e.g., "# catches RuntimeError/ValueError and other
exceptions") to make intent clear without repeating subclasses.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 68e5df7a-c17e-4e33-897a-8d37fd519490
📒 Files selected for processing (2)
data_resource_api/app/utils/descriptor.pytests/descriptor_util_classes/test_descriptor_from_file.py
Summary
Fixes #10
When a descriptor file contains invalid JSON,
_create_descriptorcaught theValueErrorand logged it — but never assigneddescriptor_dict. The function then fell through toreturn Descriptor(descriptor_dict, file_name), raising aNameErrorthat escapedDescriptorsFromDirectory._get_from_dir'sexceptclause, crashing the data model manager.Root cause:
except ValueErrorsilently swallowed the error instead of propagating it.Fix: Re-raise as
RuntimeErrorso the caller's existingexcept (Exception, ValueError, RuntimeError)catches it andcontinues to the next file — which was the intended behavior.Changes
data_resource_api/app/utils/descriptor.py— raiseRuntimeErroron invalid JSON; addexcept RuntimeError: raiseguard so the outerexcept Exceptiondoesn't swallow ittests/descriptor_util_classes/test_descriptor_from_file.py— replace skipped stub tests with three regression tests:RuntimeErrorRuntimeErrorTest plan
pytest tests/descriptor_util_classes/test_descriptor_from_file.pyNote
Low Risk
Low risk: changes are limited to error propagation when parsing descriptor JSON and adds tests to prevent regressions. Main risk is slightly different exception behavior/message for invalid descriptor files.
Overview
Fixes descriptor loading to fail fast on invalid JSON by raising a
RuntimeError(instead of logging and later crashing due to an uninitializeddescriptor_dict), and ensures the raisedRuntimeErrorisn’t swallowed by the generic exception handler.Replaces skipped placeholder tests with regression coverage verifying
DescriptorFromFileraises on invalid JSON and directory paths, and thatDescriptorsFromDirectoryskips bad JSON while still loading valid descriptors.Written by Cursor Bugbot for commit 21a72ce. This will update automatically on new commits. Configure here.
Summary by CodeRabbit
Bug Fixes
Tests