vxcontrol/pentagi · error

failed to refine subtasks for task

Error message

failed to refine subtasks for task %d: %w

What it means

After loading existing subtasks, RefineSubtasks calls the LLM provider's RefineSubtasks to generate a new plan. This error wraps a failure of that provider call — network errors, provider API errors, malformed LLM output, or missing provider credentials. Refinement aborts before any DB mutation.

Solutions

  1. Inspect the wrapped cause in logs to identify provider vs network failure
  2. Verify provider API key and base URL in settings/.env
  3. Retry the refine operation; LLM calls are idempotent up to this point
  4. Configure a fallback provider in provider config
Defensive patterns

Strategy: retry

Validate before calling

if provider == nil { return fmt.Errorf("no provider configured") }
// pre-check credentials with a lightweight provider health/list-models call

Try / catch

plan, err := stc.taskCtx.Provider.RefineSubtasks(ctx, taskID)
if err != nil {
    if errors.Is(err, context.DeadlineExceeded) { return retryWithBackoff(err) }
    return fmt.Errorf("failed to refine subtasks for task %d: %w", taskID, err)
}

Prevention

When it happens

Trigger: The configured LLM provider is unreachable, the API key is invalid/quota-exhausted, the model returns unparseable JSON, or ctx is cancelled during the (long) LLM call.

Common situations: Expired or missing provider API key in .env; provider rate limit hit during heavy usage; model name changed after provider upgrade; request timeout on slow models.

Related errors


AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01). Data as JSON: /api/errors/e35e1fb09d1f0076. Report an issue: GitHub.

Appendix: source

Thrown at backend/pkg/controller/subtasks.go:105

			Description: info.Description,
		})
		if err != nil {
			return fmt.Errorf("failed to create subtask for task %d: %w", stc.taskCtx.TaskID, err)
		}
	}

	return nil
}

func (stc *subtaskController) RefineSubtasks(ctx context.Context) error {
	subtasks, err := stc.taskCtx.DB.GetTaskSubtasks(ctx, stc.taskCtx.TaskID)
	if err != nil {
		return fmt.Errorf("failed to get task %d subtasks: %w", stc.taskCtx.TaskID, err)
	}

	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)

View on GitHub (pinned to ea665308ba)