BUG-HUNT: [error-handling] LLMExecuteActor silently falls back to zero-context LLM execution when context hydration fails — re-introduces bug #1028 #6401

Open
opened 2026-04-09 21:00:36 +00:00 by HAL9000 · 0 comments
Owner

Bug Report: [error-handling] Swallowed hydration exception causes LLM to operate with empty context, silently defeating the fix for bug #1028

Severity Assessment

  • Impact: When context hydration fails (e.g., due to DB error, filesystem issue, or upstream service failure), the exception is swallowed and the LLM executes with zero file context. The user receives AI-generated code with no project-aware context — the exact problem bug #1028 was filed to fix. Worse, there is no indication in the ExecuteResult or user-facing output that context was missing, so degraded results appear as normal.
  • Likelihood: Medium. Any transient failure in hydrate_tiers_for_plan (DB lock, resource not found, filesystem error) triggers this path.
  • Priority: High

Location

  • File: src/cleveragents/application/services/llm_actors.py
  • Function: LLMExecuteActor.execute
  • Lines: 329–359

Description

The LLMExecuteActor.execute() method introduced context hydration to fix bug #1028 (LLM receiving zero file context during execute phase). However, the hydration call is wrapped in a broad except Exception handler that logs a warning and continues silently. This means:

  1. If hydrate_tiers_for_plan() raises for any reason, the ContextTierService remains empty.
  2. The ExecutePhaseContextAssembler.assemble() call that follows then returns None (empty tier → get_scoped_view() returns [] → method returns None per line 136).
  3. The prompt is built with context_section = "" (line 374).
  4. The LLM is invoked with no project context, re-introducing bug #1028.
  5. The ExecuteResult returned to the caller contains no indication that context was absent.

The only signal is a WARNING log entry, which is invisible in normal CLI operation and not surfaced to the user.

Evidence

# llm_actors.py, lines 329–359
if (
    self._tier_service is not None
    and self._project_repository is not None
    and self._resource_registry is not None
):
    try:
        from cleveragents.application.services.context_tier_hydrator import (
            hydrate_tiers_for_plan,
        )
        project_names = [
            pl.project_name for pl in getattr(plan, "project_links", [])
        ]
        if project_names:
            hydrate_tiers_for_plan(
                tier_service=self._tier_service,
                project_names=project_names,
                project_repository=self._project_repository,
                resource_registry=self._resource_registry,
            )
    except Exception as _hydration_exc:   # ← swallows ALL exceptions
        self._logger.warning(
            "context_hydration_failed",
            error=str(_hydration_exc),
            plan_id=plan_id,
        )
        # ← silently continues with empty context!

The chain that follows demonstrates the silent degradation:

# lines 361–370
assembled_context: AssembledContext | None = None
if self._context_assembler is not None:
    try:
        assembled_context = self._context_assembler.assemble(plan)
        # Returns None when tier is empty (no fragments after filtering)
    except Exception as _asm_err:
        self._logger.warning(...)

# lines 374–389
context_section = ""
if assembled_context is not None:  # None when hydration failed
    context_section = ...          # Never reached
# → prompt built with no context section → LLM runs blind

Expected Behavior

When context hydration fails, the execute phase should either:

  1. Raise an error (preferred for reliability) so the caller can retry or inform the user, OR
  2. Include a clear warning in the result that context was unavailable, so the user can see that the generated code was produced without project context.

At minimum, the ExecuteResult should carry a context_available: bool flag, or a warning should be appended to the stream callback.

Actual Behavior

Hydration failure is swallowed. The LLM generates code with no file context. The ExecuteResult looks identical to a successful context-aware execution. The user has no way to know the result is degraded.

Suggested Fix

Option A — propagate the error:

# llm_actors.py
hydrate_tiers_for_plan(...)  # let it raise; caller handles retry

Option B — surface the degradation in the result:

context_was_hydrated = False
try:
    hydrate_tiers_for_plan(...)
    context_was_hydrated = True
except Exception as _hydration_exc:
    self._logger.warning("context_hydration_failed", ...)
    if stream_callback is not None:
        stream_callback("execute_context_unavailable", {
            "plan_id": plan_id,
            "reason": str(_hydration_exc),
        })

Category

error-handling

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.


Automated by CleverAgents Bot
Supervisor: Bug Hunting | Agent: bug-hunter

## Bug Report: [error-handling] Swallowed hydration exception causes LLM to operate with empty context, silently defeating the fix for bug #1028 ### Severity Assessment - **Impact**: When context hydration fails (e.g., due to DB error, filesystem issue, or upstream service failure), the exception is swallowed and the LLM executes with **zero file context**. The user receives AI-generated code with no project-aware context — the exact problem bug #1028 was filed to fix. Worse, there is no indication in the `ExecuteResult` or user-facing output that context was missing, so degraded results appear as normal. - **Likelihood**: Medium. Any transient failure in `hydrate_tiers_for_plan` (DB lock, resource not found, filesystem error) triggers this path. - **Priority**: High ### Location - **File**: `src/cleveragents/application/services/llm_actors.py` - **Function**: `LLMExecuteActor.execute` - **Lines**: 329–359 ### Description The `LLMExecuteActor.execute()` method introduced context hydration to fix bug #1028 (LLM receiving zero file context during execute phase). However, the hydration call is wrapped in a broad `except Exception` handler that **logs a warning and continues silently**. This means: 1. If `hydrate_tiers_for_plan()` raises for any reason, the `ContextTierService` remains empty. 2. The `ExecutePhaseContextAssembler.assemble()` call that follows then returns `None` (empty tier → `get_scoped_view()` returns `[]` → method returns `None` per line 136). 3. The prompt is built with `context_section = ""` (line 374). 4. The LLM is invoked with **no project context**, re-introducing bug #1028. 5. The `ExecuteResult` returned to the caller contains no indication that context was absent. The only signal is a `WARNING` log entry, which is invisible in normal CLI operation and not surfaced to the user. ### Evidence ```python # llm_actors.py, lines 329–359 if ( self._tier_service is not None and self._project_repository is not None and self._resource_registry is not None ): try: from cleveragents.application.services.context_tier_hydrator import ( hydrate_tiers_for_plan, ) project_names = [ pl.project_name for pl in getattr(plan, "project_links", []) ] if project_names: hydrate_tiers_for_plan( tier_service=self._tier_service, project_names=project_names, project_repository=self._project_repository, resource_registry=self._resource_registry, ) except Exception as _hydration_exc: # ← swallows ALL exceptions self._logger.warning( "context_hydration_failed", error=str(_hydration_exc), plan_id=plan_id, ) # ← silently continues with empty context! ``` The chain that follows demonstrates the silent degradation: ```python # lines 361–370 assembled_context: AssembledContext | None = None if self._context_assembler is not None: try: assembled_context = self._context_assembler.assemble(plan) # Returns None when tier is empty (no fragments after filtering) except Exception as _asm_err: self._logger.warning(...) # lines 374–389 context_section = "" if assembled_context is not None: # None when hydration failed context_section = ... # Never reached # → prompt built with no context section → LLM runs blind ``` ### Expected Behavior When context hydration fails, the execute phase should either: 1. **Raise an error** (preferred for reliability) so the caller can retry or inform the user, OR 2. **Include a clear warning in the result** that context was unavailable, so the user can see that the generated code was produced without project context. At minimum, the `ExecuteResult` should carry a `context_available: bool` flag, or a warning should be appended to the stream callback. ### Actual Behavior Hydration failure is swallowed. The LLM generates code with no file context. The `ExecuteResult` looks identical to a successful context-aware execution. The user has no way to know the result is degraded. ### Suggested Fix Option A — propagate the error: ```python # llm_actors.py hydrate_tiers_for_plan(...) # let it raise; caller handles retry ``` Option B — surface the degradation in the result: ```python context_was_hydrated = False try: hydrate_tiers_for_plan(...) context_was_hydrated = True except Exception as _hydration_exc: self._logger.warning("context_hydration_failed", ...) if stream_callback is not None: stream_callback("execute_context_unavailable", { "plan_id": plan_id, "reason": str(_hydration_exc), }) ``` ### Category error-handling ### 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. --- **Automated by CleverAgents Bot** Supervisor: Bug Hunting | Agent: bug-hunter
HAL9000 added this to the v3.2.0 milestone 2026-04-09 21:09:19 +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#6401
No description provided.