UAT: SkillConfigSchema allows description: null but Skill domain model requires non-empty description — causes confusing ValidationError instead of clear user error #2419

Open
opened 2026-04-03 17:41:54 +00:00 by freemo · 1 comment
Owner

Metadata

  • Branch: fix/skill-schema-description-alignment
  • Commit Message: fix(skills): align SkillConfigSchema description field with Skill domain model requirement
  • Milestone: v3.5.0
  • Parent Epic: #397

Background and Context

There is a schema/domain model inconsistency in the Skills System. SkillConfigSchema.description is Optional[str] (default None), which correctly matches the specification's JSON Schema — only name is required (spec line ~32567: "required": ["name"]). However, Skill.description has min_length=1, so when a user provides a skill YAML with no description field (which is valid per the spec), _schema_to_skill_dict() converts None to '' (empty string), which then fails Pydantic validation with a cryptic ValidationError.

The CLI catches this as a PydanticValidationError and surfaces it as "Schema validation error" — but the YAML schema is valid. It is the domain model that is failing. This is misleading to users and constitutes a UX bug.

Current Behavior

When a user creates a skill YAML with only name: local/test (no description), calling SkillService().add_skill(config) raises:

ValidationError: 1 validation error for Skill
  description
    String should have at least 1 character [type=string_too_short, ...]

The CLI surfaces this as "Schema validation error", which is incorrect — the YAML schema is valid per the specification. The domain model constraint is what fails.

Code locations involved:

  1. src/cleveragents/skills/schema.py line ~200: description: str | None = Field(default=None, ...)
  2. src/cleveragents/domain/models/core/skill.py line ~130: description: str = Field(..., min_length=1, ...)
  3. src/cleveragents/application/services/skill_service.py_schema_to_skill_dict(): data["description"] = config.description if config.description else ""

Steps to reproduce:

  1. Create a skill YAML with only name: local/test (no description)
  2. Call SkillService().add_skill(config) — raises ValidationError with cryptic message

Expected Behavior

The system should handle a missing description gracefully. One of the following resolutions should be applied (preferred: option 1):

  1. Preferred: SkillConfigSchema should require description (matching the domain model), and the CLI should emit a clear, user-friendly error message such as: "Skill 'local/test' is missing a required field: description".
  2. Alternative: Skill domain model allows empty/None description (relaxes the constraint to match the spec).
  3. Alternative: _schema_to_skill_dict() detects a missing description and raises a clear, descriptive ValueError before Pydantic validation occurs.

Subtasks

  • Investigate and confirm the root cause across schema.py, skill.py, and skill_service.py
  • Decide on the resolution approach (align schema → domain, or relax domain, or add guard in service layer) — document decision in PR
  • Implement the chosen fix in the appropriate file(s)
  • Update _schema_to_skill_dict() to ensure no silent None → '' conversion occurs without a clear error
  • Add/update unit tests in Behave: add scenario for skill add with missing description field asserting a clear, user-friendly error message
  • Add/update unit tests covering SkillConfigSchema with description=None and the resulting service-layer behaviour
  • Verify coverage >= 97% via nox -s coverage_report
  • Run nox (all default sessions), fix any errors

Definition of Done

This issue is complete when:

  • All subtasks above are completed and checked off.
  • A Git commit is created where the first line of the commit message matches the Commit Message in Metadata exactly (fix(skills): align SkillConfigSchema description field with Skill domain model requirement), followed by a blank line, then additional lines providing relevant details about the implementation.
  • The commit is pushed to the remote on the branch matching the Branch in Metadata exactly (fix/skill-schema-description-alignment).
  • The commit is submitted as a pull request to master, reviewed, and merged before this issue is marked done.
  • A skill YAML with no description field produces a clear, user-friendly error message (not a cryptic ValidationError).
  • All nox stages pass.
  • Coverage >= 97%.

Automated by CleverAgents Bot
Supervisor: UAT Testing | Agent: ca-new-issue-creator

## Metadata - **Branch**: `fix/skill-schema-description-alignment` - **Commit Message**: `fix(skills): align SkillConfigSchema description field with Skill domain model requirement` - **Milestone**: v3.5.0 - **Parent Epic**: #397 ## Background and Context There is a schema/domain model inconsistency in the Skills System. `SkillConfigSchema.description` is `Optional[str]` (default `None`), which correctly matches the specification's JSON Schema — only `name` is required (spec line ~32567: `"required": ["name"]`). However, `Skill.description` has `min_length=1`, so when a user provides a skill YAML with no `description` field (which is valid per the spec), `_schema_to_skill_dict()` converts `None` to `''` (empty string), which then fails Pydantic validation with a cryptic `ValidationError`. The CLI catches this as a `PydanticValidationError` and surfaces it as "Schema validation error" — but the YAML schema **is** valid. It is the domain model that is failing. This is misleading to users and constitutes a UX bug. ## Current Behavior When a user creates a skill YAML with only `name: local/test` (no `description`), calling `SkillService().add_skill(config)` raises: ``` ValidationError: 1 validation error for Skill description String should have at least 1 character [type=string_too_short, ...] ``` The CLI surfaces this as "Schema validation error", which is incorrect — the YAML schema is valid per the specification. The domain model constraint is what fails. **Code locations involved:** 1. `src/cleveragents/skills/schema.py` line ~200: `description: str | None = Field(default=None, ...)` 2. `src/cleveragents/domain/models/core/skill.py` line ~130: `description: str = Field(..., min_length=1, ...)` 3. `src/cleveragents/application/services/skill_service.py` — `_schema_to_skill_dict()`: `data["description"] = config.description if config.description else ""` **Steps to reproduce:** 1. Create a skill YAML with only `name: local/test` (no `description`) 2. Call `SkillService().add_skill(config)` — raises `ValidationError` with cryptic message ## Expected Behavior The system should handle a missing `description` gracefully. One of the following resolutions should be applied (preferred: option 1): 1. **Preferred**: `SkillConfigSchema` should require `description` (matching the domain model), and the CLI should emit a clear, user-friendly error message such as: `"Skill 'local/test' is missing a required field: description"`. 2. **Alternative**: `Skill` domain model allows empty/`None` description (relaxes the constraint to match the spec). 3. **Alternative**: `_schema_to_skill_dict()` detects a missing description and raises a clear, descriptive `ValueError` before Pydantic validation occurs. ## Subtasks - [ ] Investigate and confirm the root cause across `schema.py`, `skill.py`, and `skill_service.py` - [ ] Decide on the resolution approach (align schema → domain, or relax domain, or add guard in service layer) — document decision in PR - [ ] Implement the chosen fix in the appropriate file(s) - [ ] Update `_schema_to_skill_dict()` to ensure no silent `None → ''` conversion occurs without a clear error - [ ] Add/update unit tests in Behave: add scenario for `skill add` with missing `description` field asserting a clear, user-friendly error message - [ ] Add/update unit tests covering `SkillConfigSchema` with `description=None` and the resulting service-layer behaviour - [ ] Verify coverage >= 97% via `nox -s coverage_report` - [ ] Run `nox` (all default sessions), fix any errors ## Definition of Done This issue is complete when: - All subtasks above are completed and checked off. - A Git commit is created where the **first line** of the commit message matches the Commit Message in Metadata exactly (`fix(skills): align SkillConfigSchema description field with Skill domain model requirement`), followed by a blank line, then additional lines providing relevant details about the implementation. - The commit is pushed to the remote on the branch matching the **Branch** in Metadata exactly (`fix/skill-schema-description-alignment`). - The commit is submitted as a **pull request** to `master`, reviewed, and **merged** before this issue is marked done. - A skill YAML with no `description` field produces a clear, user-friendly error message (not a cryptic `ValidationError`). - All nox stages pass. - Coverage >= 97%. --- **Automated by CleverAgents Bot** Supervisor: UAT Testing | Agent: ca-new-issue-creator
freemo added this to the v3.5.0 milestone 2026-04-03 17:41:59 +00:00
Author
Owner

Issue triaged by project owner:

  • State: Verified
  • Priority: Low — SkillConfigSchema allowing description: null causes a confusing ValidationError instead of a clear user error. This is a UX improvement for error messages.
  • Milestone: v3.5.0
  • MoSCoW: Could Have — The validation still catches the error, just with a confusing message. Improving the error message is nice-to-have.

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

Issue triaged by project owner: - **State**: Verified - **Priority**: Low — `SkillConfigSchema` allowing `description: null` causes a confusing `ValidationError` instead of a clear user error. This is a UX improvement for error messages. - **Milestone**: v3.5.0 - **MoSCoW**: Could Have — The validation still catches the error, just with a confusing message. Improving the error message is nice-to-have. --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: ca-project-owner
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#2419
No description provided.