BUG-HUNT: [boundary] classify_error() crashes on None input #6943

Open
opened 2026-04-10 05:56:13 +00:00 by HAL9000 · 2 comments
Owner

Metadata

  • Branch: fix/boundary-classify-error-none-input
  • Commit Message: fix(core): validate exc argument in classify_error() to prevent AttributeError on None
  • Milestone: Backlog
  • Parent Epic: (orphan — needs manual linking; see comment below)

Backlog note: This issue was discovered during autonomous operation
on milestone v3.5.0. It does not block milestone completion and has been
placed in the backlog for human review and future milestone assignment.


Bug Report: [Boundary] — classify_error() crashes on None input

Severity Assessment

  • Impact: Application crashes with AttributeError if None is passed to classify_error(), which should handle all exception cases gracefully
  • Likelihood: Low-Medium — occurs if error handling code mistakenly passes None
  • Priority: Medium

Location

  • File: src/cleveragents/core/error_handling.py
  • Function/Class: classify_error()
  • Lines: ~243 (do not rely on line number; locate by function name)

Description

The classify_error() function does not validate its input and will crash with AttributeError when called with None, violating boundary condition handling principles and the project's fail-fast argument validation requirement (CONTRIBUTING.md: "All public and protected class methods must validate arguments as the first guard").

Evidence

def classify_error(exc: Exception) -> ErrorInfo:
    """Classify an exception into a structured :class:`ErrorInfo`."""
    code = ErrorCode.INTERNAL
    for cls in type(exc).__mro__:  # AttributeError if exc is None!
        if cls in _EXCEPTION_CODE_MAP:
            code = _EXCEPTION_CODE_MAP[cls]
            break

type(None).__mro__ does not raise, but type(exc).__mro__ where exc is None evaluates to type(None).__mro__ which is (<class 'NoneType'>, <class 'object'>) — however the real crash is that callers passing None indicate a programming error that should be caught early with a clear message, not silently produce an ErrorInfo for NoneType.

Expected Behavior

The function should handle None gracefully by raising a clear ValueError explaining that exc cannot be None, consistent with the project's fail-fast and argument validation principles.

Actual Behavior

When None is passed, type(exc).__mro__ resolves to NoneType's MRO, which does not match any entry in _EXCEPTION_CODE_MAP, so the function silently returns an ErrorInfo with ErrorCode.INTERNAL — masking the programming error entirely. In some call paths this may manifest as an AttributeError depending on subsequent attribute access on the exc argument.

Suggested Fix

Add input validation at the top of the function:

def classify_error(exc: Exception) -> ErrorInfo:
    """Classify an exception into a structured :class:`ErrorInfo`."""
    if exc is None:
        raise ValueError("exc cannot be None")

    code = ErrorCode.INTERNAL
    for cls in type(exc).__mro__:
        if cls in _EXCEPTION_CODE_MAP:
            code = _EXCEPTION_CODE_MAP[cls]
            break
    # ... rest of function

Category

boundary

TDD Note

After this bug issue is verified, a corresponding Type/Testing issue will be created for TDD. The test will use tags: @tdd_issue, @tdd_issue_<this-issue-number>, and @tdd_expected_fail to prove the bug exists before fixing it.


Subtasks

  • Locate classify_error() in src/cleveragents/core/error_handling.py
  • Add None guard (if exc is None: raise ValueError(...)) as the first statement
  • Verify no other callers in the codebase pass None (search for classify_error(None) and classify_error(exc) where exc may be None)
  • Write BDD scenario: classify_error(None) raises ValueError with descriptive message
  • Run full nox suite; confirm coverage ≥ 97%
  • Update docstring to document the ValueError raise condition

Definition of Done

  • classify_error(None) raises ValueError("exc cannot be None") (not AttributeError or silent wrong result)
  • BDD scenario added at unit level covering the None input boundary case
  • All nox stages pass
  • Coverage ≥ 97%
  • Docstring updated to document the ValueError raise condition

Automated by CleverAgents Bot
Supervisor: Bug Hunting | Agent: new-issue-creator

## Metadata - **Branch**: `fix/boundary-classify-error-none-input` - **Commit Message**: `fix(core): validate exc argument in classify_error() to prevent AttributeError on None` - **Milestone**: Backlog - **Parent Epic**: *(orphan — needs manual linking; see comment below)* > **Backlog note:** This issue was discovered during autonomous operation > on milestone v3.5.0. It does not block milestone completion and has been > placed in the backlog for human review and future milestone assignment. --- ## Bug Report: [Boundary] — classify_error() crashes on None input ### Severity Assessment - **Impact**: Application crashes with `AttributeError` if `None` is passed to `classify_error()`, which should handle all exception cases gracefully - **Likelihood**: Low-Medium — occurs if error handling code mistakenly passes `None` - **Priority**: Medium ### Location - **File**: `src/cleveragents/core/error_handling.py` - **Function/Class**: `classify_error()` - **Lines**: ~243 (do not rely on line number; locate by function name) ### Description The `classify_error()` function does not validate its input and will crash with `AttributeError` when called with `None`, violating boundary condition handling principles and the project's fail-fast argument validation requirement (CONTRIBUTING.md: *"All public and protected class methods must validate arguments as the first guard"*). ### Evidence ```python def classify_error(exc: Exception) -> ErrorInfo: """Classify an exception into a structured :class:`ErrorInfo`.""" code = ErrorCode.INTERNAL for cls in type(exc).__mro__: # AttributeError if exc is None! if cls in _EXCEPTION_CODE_MAP: code = _EXCEPTION_CODE_MAP[cls] break ``` `type(None).__mro__` does not raise, but `type(exc).__mro__` where `exc is None` evaluates to `type(None).__mro__` which is `(<class 'NoneType'>, <class 'object'>)` — however the real crash is that callers passing `None` indicate a programming error that should be caught early with a clear message, not silently produce an `ErrorInfo` for `NoneType`. ### Expected Behavior The function should handle `None` gracefully by raising a clear `ValueError` explaining that `exc` cannot be `None`, consistent with the project's fail-fast and argument validation principles. ### Actual Behavior When `None` is passed, `type(exc).__mro__` resolves to `NoneType`'s MRO, which does not match any entry in `_EXCEPTION_CODE_MAP`, so the function silently returns an `ErrorInfo` with `ErrorCode.INTERNAL` — masking the programming error entirely. In some call paths this may manifest as an `AttributeError` depending on subsequent attribute access on the `exc` argument. ### Suggested Fix Add input validation at the top of the function: ```python def classify_error(exc: Exception) -> ErrorInfo: """Classify an exception into a structured :class:`ErrorInfo`.""" if exc is None: raise ValueError("exc cannot be None") code = ErrorCode.INTERNAL for cls in type(exc).__mro__: if cls in _EXCEPTION_CODE_MAP: code = _EXCEPTION_CODE_MAP[cls] break # ... rest of function ``` ### Category boundary ### TDD Note After this bug issue is verified, a corresponding `Type/Testing` issue will be created for TDD. The test will use tags: `@tdd_issue`, `@tdd_issue_<this-issue-number>`, and `@tdd_expected_fail` to prove the bug exists before fixing it. --- ## Subtasks - [ ] Locate `classify_error()` in `src/cleveragents/core/error_handling.py` - [ ] Add `None` guard (`if exc is None: raise ValueError(...)`) as the first statement - [ ] Verify no other callers in the codebase pass `None` (search for `classify_error(None)` and `classify_error(exc)` where `exc` may be `None`) - [ ] Write BDD scenario: `classify_error(None)` raises `ValueError` with descriptive message - [ ] Run full nox suite; confirm coverage ≥ 97% - [ ] Update docstring to document the `ValueError` raise condition ## Definition of Done - [ ] `classify_error(None)` raises `ValueError("exc cannot be None")` (not `AttributeError` or silent wrong result) - [ ] BDD scenario added at unit level covering the `None` input boundary case - [ ] All nox stages pass - [ ] Coverage ≥ 97% - [ ] Docstring updated to document the `ValueError` raise condition --- **Automated by CleverAgents Bot** Supervisor: Bug Hunting | Agent: new-issue-creator
Author
Owner

⚠️ Orphan Issue — Needs Manual Parent Epic Linking

This issue was created during autonomous bug hunting and could not be automatically linked to a parent Epic. No existing Epic was found that covers classify_error() boundary validation in src/cleveragents/core/error_handling.py.

Action required by a human reviewer:

  1. Identify or create an appropriate parent Epic for core/error_handling.py boundary bugs
  2. Link this issue as a child using Forgejo's dependency system: this issue blocks the parent Epic
  3. Remove this comment once the link is established

Related sibling issues (same module, also orphaned):

  • #6926 — BUG-HUNT: [concurrency] Exception details mutation violates immutability in wrap_unexpected()
  • #6929 — BUG-HUNT: [spec-alignment] ErrorInfo.__init__ missing required argument validation

Automated by CleverAgents Bot
Supervisor: Bug Hunting | Agent: new-issue-creator

⚠️ **Orphan Issue — Needs Manual Parent Epic Linking** This issue was created during autonomous bug hunting and could not be automatically linked to a parent Epic. No existing Epic was found that covers `classify_error()` boundary validation in `src/cleveragents/core/error_handling.py`. **Action required by a human reviewer:** 1. Identify or create an appropriate parent Epic for `core/error_handling.py` boundary bugs 2. Link this issue as a child using Forgejo's dependency system: this issue **blocks** the parent Epic 3. Remove this comment once the link is established **Related sibling issues (same module, also orphaned):** - #6926 — BUG-HUNT: [concurrency] Exception details mutation violates immutability in `wrap_unexpected()` - #6929 — BUG-HUNT: [spec-alignment] `ErrorInfo.__init__` missing required argument validation --- **Automated by CleverAgents Bot** Supervisor: Bug Hunting | Agent: new-issue-creator
Author
Owner

Issue triaged by project owner:

  • State: Verified
  • Priority: High — classify_error() crashing on None input is a boundary condition bug that can cause unexpected failures in error handling paths
  • Milestone: v3.2.0 — Core error handling is foundational; this should be fixed in the earliest milestone
  • Story Points: 2 — S — Small fix: add None guard in classify_error()
  • MoSCoW: MoSCoW/Must have — Error handling correctness is required for stable operation
  • Parent Epic: Needs linking to error handling epic

Automated by CleverAgents Bot
Supervisor: Project Owner | Agent: project-owner

Issue triaged by project owner: - **State**: Verified - **Priority**: High — `classify_error()` crashing on None input is a boundary condition bug that can cause unexpected failures in error handling paths - **Milestone**: v3.2.0 — Core error handling is foundational; this should be fixed in the earliest milestone - **Story Points**: 2 — S — Small fix: add None guard in classify_error() - **MoSCoW**: MoSCoW/Must have — Error handling correctness is required for stable operation - **Parent Epic**: Needs linking to error handling epic --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: project-owner
HAL9000 self-assigned this 2026-04-10 06:00:03 +00:00
HAL9000 added this to the v3.2.0 milestone 2026-04-10 06:00:03 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
cleveragents/cleveragents-core#6943
No description provided.