vxcontrol/pentagi · error
failed to delete subtasks for task %d: %w
Error message
failed to delete subtasks for task %d: %w
What it means
RefineSubtasks deletes the obsolete subtask IDs in the database before inserting the refined plan. This error wraps a failure of DeleteSubtasks. Because delete and insert are not yet transactional (see the TODO), a failure here leaves the task in the pre-refinement state, which is recoverable by re-running.
Source
Thrown at backend/pkg/controller/subtasks.go:121
plan, err := stc.taskCtx.Provider.RefineSubtasks(ctx, stc.taskCtx.TaskID)
if err != nil {
return fmt.Errorf("failed to refine subtasks for task %d: %w", stc.taskCtx.TaskID, err)
}
if len(plan) == 0 {
return nil // no subtasks refined
}
subtaskIDs := make([]int64, 0, len(subtasks))
for _, subtask := range subtasks {
if subtask.Status == database.SubtaskStatusCreated {
subtaskIDs = append(subtaskIDs, subtask.ID)
}
}
err = stc.taskCtx.DB.DeleteSubtasks(ctx, subtaskIDs)
if err != nil {
return fmt.Errorf("failed to delete subtasks for task %d: %w", stc.taskCtx.TaskID, err)
}
stc.InvalidateSubtasks(subtaskIDs)
// TODO: change it to insert subtasks in transaction and union it with delete ones
for _, info := range plan {
_, err := stc.taskCtx.DB.CreateSubtask(ctx, database.CreateSubtaskParams{
Status: database.SubtaskStatusCreated,
TaskID: stc.taskCtx.TaskID,
Title: info.Title,
Description: info.Description,
})
if err != nil {
return fmt.Errorf("failed to create subtask for task %d: %w", stc.taskCtx.TaskID, err)
}
}
return nil
}View on GitHub (pinned to ea665308ba)
Solutions
- Check the wrapped DB error in logs for constraint/connection details
- Retry RefineSubtasks — deletes happen before inserts so no partial plan exists
- Verify FK constraints on subtasks table (dependent rows must be deleted first)
- Run delete+insert inside a single transaction to make refinement atomic
Example fix
// before
err = stc.taskCtx.DB.DeleteSubtasks(ctx, subtaskIDs)
if err != nil {
return fmt.Errorf("failed to delete subtasks for task %d: %w", stc.taskCtx.TaskID, err)
}
// after
if len(subtaskIDs) > 0 {
err = stc.taskCtx.DB.DeleteSubtasks(ctx, subtaskIDs)
if err != nil {
return fmt.Errorf("failed to delete subtasks for task %d: %w", stc.taskCtx.TaskID, err)
}
} Defensive patterns
Strategy: try-catch
Validate before calling
if len(subtaskIDs) == 0 { /* skip delete */ } Try / catch
if err := stc.taskCtx.DB.DeleteSubtasks(ctx, subtaskIDs); err != nil {
var pqErr *pq.Error
if errors.As(err, &pqErr) { log.Error("delete failed", "constraint", pqErr.Constraint) }
return fmt.Errorf("failed to delete subtasks for task %d: %w", taskID, err)
} Prevention
- Wrap delete+insert in one transaction (resolve the code TODO)
- Check FK constraints on subtask-dependent tables
- Verify no concurrent refinement of the same task
When it happens
Trigger: DeleteSubtasks fails due to DB connection loss, context cancellation, FK constraint blocking a delete, or an empty/large ID list hitting query limits.
Common situations: Postgres connection pool exhausted during concurrent flows; long-running refine transaction timing out; DB read replica used for writes by misconfiguration.
Related errors
- failed to delete assistant %d: %w
- failed to delete provider: %w
- failed to delete destination for overwrite: %w
- failed to delete merged source directory %q: %w
- failed to delete source directory %q: %w
AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01).
Data as JSON: /api/errors/ce768cd1b8f5603e.
Report an issue: GitHub.