vxcontrol/pentagi · error

failed to get subtasks: %w

Error message

failed to get subtasks: %w

What it means

Thrown in buildSubtasksList (backend/pkg/tools/flow_manager.go:221) when either GetFlowTaskSubtasks (filtered by task_id) or GetFlowSubtasks (whole flow) fails. It means get_flow_status with detail='subtasks' could not read the subtask rows; the wrapped cause carries the actual database error.

Source

Thrown at backend/pkg/tools/flow_manager.go:221

	return taskList, nil
}

func (t *flowStatusTool) buildSubtasksList(ctx context.Context, taskID *int64, verbose bool) (string, error) {
	var subtasks []database.Subtask
	var err error

	if taskID != nil && *taskID > 0 {
		subtasks, err = t.db.GetFlowTaskSubtasks(ctx, database.GetFlowTaskSubtasksParams{
			FlowID: t.flowID,
			TaskID: *taskID,
		})
	} else {
		subtasks, err = t.db.GetFlowSubtasks(ctx, t.flowID)
	}

	if err != nil {
		return "", fmt.Errorf("failed to get subtasks: %w", err)
	}

	if len(subtasks) == 0 {
		return "No subtasks found.", nil
	}

	sb := &strings.Builder{}
	if taskID != nil && *taskID > 0 {
		fmt.Fprintf(sb, "Subtasks for task %d:\n\n", *taskID)
	} else {
		fmt.Fprintf(sb, "All subtasks for flow %d:\n\n", t.flowID)
	}
	for _, st := range subtasks {
		fmt.Fprintf(sb, "Subtask ID: %d | Task ID: %d | Status: %s | Title: %s\n",
			st.ID, st.TaskID, st.Status, st.Title)
		if verbose {
			if st.Description != "" {
				description, err := t.getDescriptionText(ctx, st.Description)

View on GitHub (pinned to ea665308ba)

Solutions

  1. Confirm PostgreSQL health and connectivity (pg_isready, docker compose logs postgres); restart if degraded.
  2. Unwrap the cause from logs and address it specifically (auth, timeout, undefined table).
  3. Re-run goose migrations (backend/migrations/sql) if schema drift is detected and restart the backend.
  4. Retry the tool call after DB recovery; tune pool/timeout settings if exhaustion was the cause.

Example fix

// before
if err != nil {
	return "", fmt.Errorf("failed to get subtasks: %w", err)
}
// after: add one retry for transient DB errors
subtasks, err = t.db.GetFlowSubtasks(ctx, t.flowID)
if err != nil && isTransientDBError(err) {
	time.Sleep(500 * time.Millisecond)
	subtasks, err = t.db.GetFlowSubtasks(ctx, t.flowID)
}
if err != nil {
	return "", fmt.Errorf("failed to get subtasks: %w", err)
}
Defensive patterns

Strategy: retry

Validate before calling

// validate DB access and args before the tool call
if err := db.PingContext(ctx); err != nil {
	return fmt.Errorf("postgres unreachable: %w", err)
}
if taskID != nil && *taskID <= 0 {
	taskID = nil // fall back to flow-wide subtask query
}

Try / catch

// Go: bounded retry with DB-error classification
var out string
err := retry.OnError(ctx, 3, isTransientDBError, func() error {
	var e error
	out, e = tool.Handle(ctx, "get_flow_status", subtasksArgs)
	return e
})
if err != nil {
	return fmt.Errorf("subtasks listing failed: %w", err)
}

Prevention

When it happens

Trigger: get_flow_status with detail='subtasks' where the DB query fails — PostgreSQL unreachable, statement/context timeout, connection-pool exhaustion, or a schema mismatch (e.g. missing subtasks table after failed migration); also fires with a bad task_id only if the query itself errors, not when rows are empty.

Common situations: Database restart or failover during an agent session; DB credentials rotated in .env without backend restart... actually with restart needed; goose migration partially applied leaving schema drift; heavy concurrent load saturating pg connections.

Understand the failure class

Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.

Related errors


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