UAT: plan status command does not handle NotFoundError when plan_id is a valid ULID but plan does not exist #5424

Open
opened 2026-04-09 06:38:45 +00:00 by HAL9000 · 1 comment
Owner

Bug Report

Feature Area: Plan Lifecycle Core — agents plan status
Severity: Priority/Backlog (error handling gap, not blocking core lifecycle)

What Was Tested

Code-level analysis of agents plan status <valid-ulid-that-doesnt-exist> against the specification's error handling requirements.

Expected Behavior (from spec)

When a valid ULID is provided but no plan with that ID exists, the command should display a clear, user-friendly error message: "Plan '' not found."

Actual Behavior

The plan_status command at src/cleveragents/cli/commands/plan.py lines 2309–2395 calls service.get_plan(plan_id) at line 2384, which raises NotFoundError when the plan doesn't exist. NotFoundError is a subclass of CleverAgentsError, so it IS caught by the except CleverAgentsError handler at line 2393.

However, the error message displayed will be the generic NotFoundError message format: "plan 'XXXX' not found" — which is technically correct but inconsistent with how other commands handle this case (e.g., plan execute and plan apply both explicitly check if plan is None and print a custom message before aborting).

More importantly, the plan_status command does NOT validate the ULID format before querying the database (unlike plan execute, plan apply, plan cancel, and plan diff which all call _validate_plan_ulid(plan_id) first). This means:

  1. A non-ULID string like "my-plan-name" will be passed directly to service.get_plan()
  2. The service will fail to find it and raise NotFoundError
  3. The error message will NOT include the helpful "legacy vs v3 workflow" explanation that _validate_plan_ulid provides

Code Location

  • Bug: src/cleveragents/cli/commands/plan.py, line 2381 (the plan_status command's single-plan lookup path)
  • Missing: _validate_plan_ulid(plan_id) call before service.get_plan(plan_id) at line 2384
  • Fix: Add _validate_plan_ulid(plan_id) call at line 2381 (before the service.get_plan call), consistent with all other plan commands

Comparison

All other plan commands that accept a plan_id argument call _validate_plan_ulid first:

  • plan execute (line 2023): calls _validate_plan_ulid(plan_id)
  • plan apply (line 2225): calls _validate_plan_ulid(plan_id)
  • plan cancel (line 2802): calls _validate_plan_ulid(plan_id)
  • plan diff (line 2918): uses plan_id argument (no ULID validation)
  • plan status (line 2381): missing _validate_plan_ulid(plan_id) call

Automated by CleverAgents Bot
Supervisor: UAT Testing | Agent: uat-tester

## Bug Report **Feature Area**: Plan Lifecycle Core — `agents plan status` **Severity**: Priority/Backlog (error handling gap, not blocking core lifecycle) ## What Was Tested Code-level analysis of `agents plan status <valid-ulid-that-doesnt-exist>` against the specification's error handling requirements. ## Expected Behavior (from spec) When a valid ULID is provided but no plan with that ID exists, the command should display a clear, user-friendly error message: "Plan '<id>' not found." ## Actual Behavior The `plan_status` command at `src/cleveragents/cli/commands/plan.py` lines 2309–2395 calls `service.get_plan(plan_id)` at line 2384, which raises `NotFoundError` when the plan doesn't exist. `NotFoundError` is a subclass of `CleverAgentsError`, so it IS caught by the `except CleverAgentsError` handler at line 2393. However, the error message displayed will be the generic `NotFoundError` message format: `"plan 'XXXX' not found"` — which is technically correct but inconsistent with how other commands handle this case (e.g., `plan execute` and `plan apply` both explicitly check `if plan is None` and print a custom message before aborting). More importantly, the `plan_status` command does NOT validate the ULID format before querying the database (unlike `plan execute`, `plan apply`, `plan cancel`, and `plan diff` which all call `_validate_plan_ulid(plan_id)` first). This means: 1. A non-ULID string like `"my-plan-name"` will be passed directly to `service.get_plan()` 2. The service will fail to find it and raise `NotFoundError` 3. The error message will NOT include the helpful "legacy vs v3 workflow" explanation that `_validate_plan_ulid` provides ## Code Location - **Bug**: `src/cleveragents/cli/commands/plan.py`, line 2381 (the `plan_status` command's single-plan lookup path) - **Missing**: `_validate_plan_ulid(plan_id)` call before `service.get_plan(plan_id)` at line 2384 - **Fix**: Add `_validate_plan_ulid(plan_id)` call at line 2381 (before the `service.get_plan` call), consistent with all other plan commands ## Comparison All other plan commands that accept a `plan_id` argument call `_validate_plan_ulid` first: - `plan execute` (line 2023): ✅ calls `_validate_plan_ulid(plan_id)` - `plan apply` (line 2225): ✅ calls `_validate_plan_ulid(plan_id)` - `plan cancel` (line 2802): ✅ calls `_validate_plan_ulid(plan_id)` - `plan diff` (line 2918): ✅ uses `plan_id` argument (no ULID validation) - `plan status` (line 2381): ❌ **missing** `_validate_plan_ulid(plan_id)` call --- **Automated by CleverAgents Bot** Supervisor: UAT Testing | Agent: uat-tester
HAL9000 added this to the v3.2.0 milestone 2026-04-09 06:49:36 +00:00
Author
Owner

Label compliance fix applied:

  • Added missing labels to bring issue into compliance with CONTRIBUTING.md

Automated by CleverAgents Bot
Supervisor: Backlog Grooming | Agent: backlog-groomer

Label compliance fix applied: - Added missing labels to bring issue into compliance with CONTRIBUTING.md --- **Automated by CleverAgents Bot** Supervisor: Backlog Grooming | Agent: backlog-groomer
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#5424
No description provided.