Hmbown/CodeWhale · error

task was created but Work lifecycle reconciliation failed

Error message

task was created but Work lifecycle reconciliation failed

What it means

This is a ToolError::execution_failed raised in tasks.rs when a task record was successfully created but the follow-up reconciliation with the Work lifecycle (reconcile_task_record) failed. The library treats the lifecycle sync as a post-create step: the task exists, so the error carries a warning flavor but is surfaced as an execution failure string so the agent/user knows the task is not fully registered with the Work lifecycle.

Solutions

  1. Note that the task WAS created — do not recreate it; instead retry the reconciliation (re-running the tool may duplicate the task).
  2. Check that the Work lifecycle state exists in the session context and is initialized before creating tasks.
  3. Inspect the underlying error text (it is included in the ToolError) for the specific lifecycle failure and fix that state.
  4. If lifecycle records drifted, repair or reset the lifecycle record for the task id rather than deleting the task.
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure Work lifecycle context is initialized before creating tasks
if context.lifecycle_store().is_err() {
    return Err(ToolError::execution_failed("Work lifecycle not initialized"));
}

Try / catch

match reconcile_task_record(context, &task) {
    Err(err) => tracing::warn!(task_id = %task.id, "created but reconciliation failed: {err}"),
    Ok(_) => {}
}

Prevention

When it happens

Trigger: Calling the task_create tool's execute path where the task is created fine but reconcile_task_record(context, &task) returns Err — e.g. the Work lifecycle store is unavailable, the record cannot be linked, or lifecycle state validation rejects the new task.

Common situations: Work lifecycle state missing or not initialized in the session context; a task created outside the tool (manual edits) leaving inconsistent lifecycle state; schema drift between task records and the lifecycle store.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15). Data as JSON: /api/errors/a5ec95fe22daa635. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/tools/tasks.rs:521

        }
        let task = match manager.add_task_with_id(req, task_id.clone()).await {
            Ok(task) => task,
            Err(err) => {
                if let Some(work) = context.runtime.work.as_ref() {
                    let _ = work.reconcile_operation(
                        &context.state_namespace,
                        OperationOwnerSnapshot::new(
                            format!("task:{task_id}"),
                            OwnerState::Failed,
                            1,
                            Utc::now().timestamp_millis(),
                        ),
                    );
                }
                return Err(ToolError::execution_failed(err.to_string()));
            }
        };
        let lifecycle_warning = reconcile_task_record(context, &task).err().map(|err| {
            tracing::warn!(task_id = %task.id, error = %err, "task was created but Work lifecycle reconciliation failed");
            err.to_string()
        });
        task_result_with_lifecycle_warning("task_create", &task, lifecycle_warning.as_deref())
    }

    async fn execute_list(
        &self,
        input: &Value,
        context: &ToolContext,
    ) -> Result<ToolResult, ToolError> {
        let manager = context
            .runtime
            .task_manager
            .as_ref()
            .ok_or_else(|| ToolError::not_available("TaskManager is not attached"))?;
        let limit = optional_u64(input, "limit", 20)?.clamp(1, 100) as usize;
        let tasks = manager

View on GitHub (pinned to 433685b202)