tui/persona/registry: PersonaRegistry.get() raises unhandled yaml.YAMLError/ValidationError on corrupted persona file #10375

Open
opened 2026-04-18 09:15:35 +00:00 by HAL9000 · 1 comment
Owner

Metadata

  • Commit message: fix(tui/persona/registry): catch yaml.YAMLError and ValidationError in PersonaRegistry.get()
  • Branch: fix/persona-registry-get-error-handling

Background and Context

PersonaRegistry.get() in src/cleveragents/tui/persona/registry.py does not catch yaml.YAMLError or pydantic.ValidationError, unlike list_personas() which handles these gracefully. A corrupted persona YAML file causes an unhandled exception that crashes the TUI on every input submission. This is inconsistent with list_personas() which gracefully skips invalid files.

get() is called from PersonaState.active_persona()_refresh_persona_bar() in app.py, which is called on every input submission. A corrupted persona file will crash the TUI on every keystroke.

Expected Behavior

get() should return None for corrupted or schema-invalid persona files, consistent with list_personas() which logs a warning and skips invalid files.

Acceptance Criteria

  • PersonaRegistry.get() catches (yaml.YAMLError, ValidationError) and returns None
  • A warning is logged when a corrupted file is encountered (consistent with list_personas())
  • TUI does not crash when a persona YAML file is corrupted
  • All TDD tests from #10372 pass
  • No regression in existing persona loading behavior

Subtasks

  • Add try/except block in PersonaRegistry.get() wrapping yaml.safe_load() and Persona.model_validate()
  • Log a warning on exception (consistent with list_personas())
  • Return None on exception
  • Verify all TDD tests from #10372 pass
  • Verify no regression in existing tests

Bug Report

Summary

PersonaRegistry.get() does not catch yaml.YAMLError or pydantic.ValidationError, unlike list_personas() which handles these gracefully. A corrupted persona YAML file causes an unhandled exception that crashes the TUI on every input submission.

Code Evidence

File: src/cleveragents/tui/persona/registry.py

list_personas() (line 104-113) correctly handles errors:

def list_personas(self) -> list[Persona]:
    ...
    for file in sorted(self.personas_dir.glob("*.y*ml")):
        try:
            raw = yaml.safe_load(file.read_text(encoding="utf-8")) or {}
            if not isinstance(raw, dict):
                continue
            personas.append(Persona.model_validate(raw))
        except (yaml.YAMLError, ValidationError) as exc:
            _logger.warning("Skipping invalid persona file %s: %s", file, exc)
    return personas

get() (line 116-123) does NOT handle errors:

def get(self, name: str) -> Persona | None:
    file = self.persona_path(name)
    if not file.exists():
        return None
    raw = yaml.safe_load(file.read_text(encoding="utf-8")) or {}  # ← unhandled yaml.YAMLError
    if not isinstance(raw, dict):
        return None
    return Persona.model_validate(raw)  # ← unhandled ValidationError

Call Chain

get() is called from PersonaState.active_persona()_refresh_persona_bar() in app.py, which is called on every input submission. A corrupted persona file will crash the TUI on every keystroke.

Steps to Reproduce

  1. Create a persona via the TUI
  2. Manually corrupt the persona YAML file (e.g., ~/.config/cleveragents/personas/default.yaml)
  3. Submit any input in the TUI
  4. The TUI crashes with yaml.YAMLError or pydantic.ValidationError

Expected Behavior

get() should return None for corrupted or schema-invalid persona files, consistent with list_personas() which logs a warning and skips invalid files.

Actual Behavior

get() raises an unhandled exception, crashing the TUI.

Fix Path

def get(self, name: str) -> Persona | None:
    file = self.persona_path(name)
    if not file.exists():
        return None
    try:
        raw = yaml.safe_load(file.read_text(encoding="utf-8")) or {}
        if not isinstance(raw, dict):
            return None
        return Persona.model_validate(raw)
    except (yaml.YAMLError, ValidationError) as exc:
        _logger.warning("Skipping invalid persona file %s: %s", file, exc)
        return None

Blocked By

#10372

Definition of Done

This issue should be closed when:

  • PersonaRegistry.get() catches (yaml.YAMLError, ValidationError) and returns None
  • A warning is logged when a corrupted file is encountered
  • All TDD tests from #10372 pass
  • No regression in existing persona loading behavior
  • The fix is merged to the main branch

Automated by CleverAgents Bot
Agent: new-issue-creator

## Metadata - **Commit message:** `fix(tui/persona/registry): catch yaml.YAMLError and ValidationError in PersonaRegistry.get()` - **Branch:** `fix/persona-registry-get-error-handling` ## Background and Context `PersonaRegistry.get()` in `src/cleveragents/tui/persona/registry.py` does not catch `yaml.YAMLError` or `pydantic.ValidationError`, unlike `list_personas()` which handles these gracefully. A corrupted persona YAML file causes an unhandled exception that crashes the TUI on every input submission. This is inconsistent with `list_personas()` which gracefully skips invalid files. `get()` is called from `PersonaState.active_persona()` → `_refresh_persona_bar()` in `app.py`, which is called on every input submission. A corrupted persona file will crash the TUI on every keystroke. ## Expected Behavior `get()` should return `None` for corrupted or schema-invalid persona files, consistent with `list_personas()` which logs a warning and skips invalid files. ## Acceptance Criteria - [ ] `PersonaRegistry.get()` catches `(yaml.YAMLError, ValidationError)` and returns `None` - [ ] A warning is logged when a corrupted file is encountered (consistent with `list_personas()`) - [ ] TUI does not crash when a persona YAML file is corrupted - [ ] All TDD tests from #10372 pass - [ ] No regression in existing persona loading behavior ## Subtasks - [ ] Add try/except block in `PersonaRegistry.get()` wrapping `yaml.safe_load()` and `Persona.model_validate()` - [ ] Log a warning on exception (consistent with `list_personas()`) - [ ] Return `None` on exception - [ ] Verify all TDD tests from #10372 pass - [ ] Verify no regression in existing tests ## Bug Report ### Summary `PersonaRegistry.get()` does not catch `yaml.YAMLError` or `pydantic.ValidationError`, unlike `list_personas()` which handles these gracefully. A corrupted persona YAML file causes an unhandled exception that crashes the TUI on every input submission. ### Code Evidence **File:** `src/cleveragents/tui/persona/registry.py` `list_personas()` (line 104-113) correctly handles errors: ```python def list_personas(self) -> list[Persona]: ... for file in sorted(self.personas_dir.glob("*.y*ml")): try: raw = yaml.safe_load(file.read_text(encoding="utf-8")) or {} if not isinstance(raw, dict): continue personas.append(Persona.model_validate(raw)) except (yaml.YAMLError, ValidationError) as exc: _logger.warning("Skipping invalid persona file %s: %s", file, exc) return personas ``` `get()` (line 116-123) does NOT handle errors: ```python def get(self, name: str) -> Persona | None: file = self.persona_path(name) if not file.exists(): return None raw = yaml.safe_load(file.read_text(encoding="utf-8")) or {} # ← unhandled yaml.YAMLError if not isinstance(raw, dict): return None return Persona.model_validate(raw) # ← unhandled ValidationError ``` ### Call Chain `get()` is called from `PersonaState.active_persona()` → `_refresh_persona_bar()` in `app.py`, which is called on every input submission. A corrupted persona file will crash the TUI on every keystroke. ### Steps to Reproduce 1. Create a persona via the TUI 2. Manually corrupt the persona YAML file (e.g., `~/.config/cleveragents/personas/default.yaml`) 3. Submit any input in the TUI 4. The TUI crashes with `yaml.YAMLError` or `pydantic.ValidationError` ### Expected Behavior `get()` should return `None` for corrupted or schema-invalid persona files, consistent with `list_personas()` which logs a warning and skips invalid files. ### Actual Behavior `get()` raises an unhandled exception, crashing the TUI. ### Fix Path ```python def get(self, name: str) -> Persona | None: file = self.persona_path(name) if not file.exists(): return None try: raw = yaml.safe_load(file.read_text(encoding="utf-8")) or {} if not isinstance(raw, dict): return None return Persona.model_validate(raw) except (yaml.YAMLError, ValidationError) as exc: _logger.warning("Skipping invalid persona file %s: %s", file, exc) return None ``` ### Blocked By #10372 ## Definition of Done This issue should be closed when: - `PersonaRegistry.get()` catches `(yaml.YAMLError, ValidationError)` and returns `None` - A warning is logged when a corrupted file is encountered - All TDD tests from #10372 pass - No regression in existing persona loading behavior - The fix is merged to the main branch --- **Automated by CleverAgents Bot** Agent: new-issue-creator
HAL9000 added this to the v3.7.0 milestone 2026-04-18 09:23:44 +00:00
Author
Owner

[GROOMED] Quality Analysis Report

Issue Validity: VALID & ACTIONABLE

This is a legitimate Priority/Critical bug affecting TUI stability. The issue is well-documented with:

  • Clear problem statement: PersonaRegistry.get() lacks error handling for corrupted YAML files
  • Code evidence showing the inconsistency with list_personas()
  • Reproducible steps and impact analysis
  • Proposed fix path with acceptance criteria
  • Proper blocking relationship (#10372)

Label Verification: COMPLETE

Current Labels:

  • Priority/Critical (id: 858) — Correct
  • State/Verified (id: 847) — UPDATED (was State/Unverified)
  • Type/Bug (id: 849) — Correct

Status: All required labels present. State transitioned from Unverified → Verified.

Milestone Assignment: ASSIGNED

  • Assigned to: v3.7.0 (M8: TUI Implementation)
  • Rationale: This is a critical TUI bug affecting persona registry functionality, which is core to the TUI milestone scope

Issue Quality Assessment

Aspect Status Notes
Problem Statement Excellent Clear, specific, reproducible
Code Evidence Complete Shows both broken and correct patterns
Impact Analysis High Crashes TUI on every keystroke if persona corrupted
Acceptance Criteria Well-defined 5 clear criteria with subtasks
Blocking Dependencies Documented Blocked by #10372 (TDD tests)
Fix Path Provided Includes exact code changes needed

Grooming Actions Completed

  1. Verified issue is legitimate and actionable
  2. Confirmed all required labels present
  3. Transitioned from State/Unverified → State/Verified
  4. Assigned to v3.7.0 (TUI Implementation) milestone
  5. Flagged as Priority/Critical for immediate attention

Recommendations

  • For Implementor: This issue is ready for implementation once #10372 (TDD tests) is complete
  • For Reviewer: Ensure error handling matches list_personas() pattern exactly
  • For QA: Test with manually corrupted persona YAML files in ~/.config/cleveragents/personas/

Summary

Issue #10375 is a valid, well-documented Priority/Critical bug that has been successfully groomed and is ready for the development backlog. The issue demonstrates excellent quality with clear acceptance criteria, code evidence, and a proposed fix path. It is now assigned to v3.7.0 (TUI Implementation) milestone and transitioned to State/Verified status.


Automated by CleverAgents Bot
Supervisor: Grooming | Agent: grooming-pool-supervisor

## [GROOMED] Quality Analysis Report ### Issue Validity: ✅ VALID & ACTIONABLE This is a **legitimate Priority/Critical bug** affecting TUI stability. The issue is well-documented with: - Clear problem statement: `PersonaRegistry.get()` lacks error handling for corrupted YAML files - Code evidence showing the inconsistency with `list_personas()` - Reproducible steps and impact analysis - Proposed fix path with acceptance criteria - Proper blocking relationship (#10372) ### Label Verification: ✅ COMPLETE **Current Labels:** - ✅ Priority/Critical (id: 858) — Correct - ✅ State/Verified (id: 847) — **UPDATED** (was State/Unverified) - ✅ Type/Bug (id: 849) — Correct **Status:** All required labels present. State transitioned from Unverified → Verified. ### Milestone Assignment: ✅ ASSIGNED - **Assigned to:** v3.7.0 (M8: TUI Implementation) - **Rationale:** This is a critical TUI bug affecting persona registry functionality, which is core to the TUI milestone scope ### Issue Quality Assessment | Aspect | Status | Notes | |--------|--------|-------| | Problem Statement | ✅ Excellent | Clear, specific, reproducible | | Code Evidence | ✅ Complete | Shows both broken and correct patterns | | Impact Analysis | ✅ High | Crashes TUI on every keystroke if persona corrupted | | Acceptance Criteria | ✅ Well-defined | 5 clear criteria with subtasks | | Blocking Dependencies | ✅ Documented | Blocked by #10372 (TDD tests) | | Fix Path | ✅ Provided | Includes exact code changes needed | ### Grooming Actions Completed 1. ✅ Verified issue is legitimate and actionable 2. ✅ Confirmed all required labels present 3. ✅ Transitioned from State/Unverified → State/Verified 4. ✅ Assigned to v3.7.0 (TUI Implementation) milestone 5. ✅ Flagged as Priority/Critical for immediate attention ### Recommendations - **For Implementor:** This issue is ready for implementation once #10372 (TDD tests) is complete - **For Reviewer:** Ensure error handling matches `list_personas()` pattern exactly - **For QA:** Test with manually corrupted persona YAML files in ~/.config/cleveragents/personas/ ### Summary Issue #10375 is a **valid, well-documented Priority/Critical bug** that has been successfully groomed and is ready for the development backlog. The issue demonstrates excellent quality with clear acceptance criteria, code evidence, and a proposed fix path. It is now assigned to v3.7.0 (TUI Implementation) milestone and transitioned to State/Verified status. --- **Automated by CleverAgents Bot** Supervisor: Grooming | Agent: grooming-pool-supervisor
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#10375
No description provided.