vxcontrol/pentagi · error

failed to prepare primary agent chain for subtask %d: %w

Error message

failed to prepare primary agent chain for subtask %d: %w

What it means

NewSubtaskWorker calls Provider.PrepareAgentChain to create the primary LLM message chain for a subtask and wraps any failure with the subtask ID. Failures originate in the provider layer: LLM provider misconfiguration, unavailability, or chain persistence errors in the database.

Source

Thrown at backend/pkg/controller/subtask.go:62

	updater    TaskUpdater
	completed  bool
	waiting    bool
}

func NewSubtaskWorker(
	ctx context.Context,
	taskCtx *TaskContext,
	id int64,
	title,
	description string,
	updater TaskUpdater,
) (SubtaskWorker, error) {
	ctx, span := obs.Observer.NewSpan(ctx, obs.SpanKindInternal, "controller.NewSubtaskWorker")
	defer span.End()

	msgChainID, err := taskCtx.Provider.PrepareAgentChain(ctx, taskCtx.TaskID, id)
	if err != nil {
		return nil, fmt.Errorf("failed to prepare primary agent chain for subtask %d: %w", id, err)
	}

	return &subtaskWorker{
		mx: &sync.RWMutex{},
		subtaskCtx: &SubtaskContext{
			MsgChainID:         msgChainID,
			SubtaskID:          id,
			SubtaskTitle:       title,
			SubtaskDescription: description,
			TaskContext:        *taskCtx,
		},
		updater:   updater,
		completed: false,
		waiting:   false,
	}, nil
}

func LoadSubtaskWorker(

View on GitHub (pinned to ea665308ba)

Solutions

  1. Inspect the wrapped cause (%w) to see whether the failure is provider-side or database-side.
  2. Verify at least one LLM provider is configured with valid credentials in .env / provider settings.
  3. Test provider reachability (API key, base URL, network egress) with a minimal request.
  4. Check DB health and that message-chain tables/migrations are intact.
  5. Retry the subtask; chain preparation may succeed once a transient provider outage ends.

Example fix

// before
subtaskWorker, err := controller.NewSubtaskWorker(ctx, taskCtx, id)
if err != nil {
    log.Fatal(err)
}
// after
subtaskWorker, err := controller.NewSubtaskWorker(ctx, taskCtx, id)
if err != nil {
    log.Warn("chain prep failed, requeueing subtask", "id", id, "err", err)
    queue.Requeue(id) // retry later instead of crashing
    return
}
Defensive patterns

Strategy: retry

Validate before calling

// preflight: confirm a provider is configured and reachable
if taskCtx.Provider == nil {
    return fmt.Errorf("no LLM provider configured")
}
if err := taskCtx.Provider.HealthCheck(ctx); err != nil {
    return fmt.Errorf("provider unhealthy: %w", err)
}

Type guard

func IsChainPrepError(err error) (subtaskID int64, ok bool) {
    return subtaskID, strings.Contains(err.Error(), "failed to prepare primary agent chain")
}

Try / catch

worker, err := controller.NewSubtaskWorker(ctx, taskCtx, subtaskID)
if err != nil {
    log.Warn("prepare chain failed", "subtask", subtaskID, "err", err)
    if retryable(err) {
        queue.RequeueAfter(subtaskID, backoff)
        return nil
    }
    return err
}

Prevention

When it happens

Trigger: PopSubtask dequeues a subtask and calls NewSubtaskWorker while PrepareAgentChain fails — e.g. no LLM provider configured/healthy, provider API key invalid, or the DB insert of the message chain fails.

Common situations: Missing or expired provider API keys in .env; all configured providers rate-limited or down; database connectivity issues during chain creation; provider type not registered/whitelisted after a config change.

Related errors


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