vxcontrol/pentagi · error

failed to perform agent chain for subtask %d: %w

Error message

failed to perform agent chain for subtask %d: %w

What it means

Run executes the LLM agent chain via Provider.PerformAgentChain. On any error from that call, the subtask is reset to Waiting, chain consistency is re-attempted (joined via errors.Join on failure), and the combined error is wrapped as 'failed to perform agent chain for subtask %d'. This is the top-level wrapper for all LLM/tool failures during subtask execution.

Source

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

		msgChainID = stw.subtaskCtx.MsgChainID
	)

	if err := stw.subtaskCtx.Provider.EnsureChainConsistency(ctx, msgChainID); err != nil {
		stw.handleInterrupting(err)
		return fmt.Errorf("failed to ensure chain consistency for subtask %d: %w", subtaskID, err)
	}

	performResult, err := stw.subtaskCtx.Provider.PerformAgentChain(ctx, taskID, subtaskID, msgChainID)
	if err != nil {
		if errors.Is(err, context.Canceled) {
			ctx = context.Background()
		}
		errChainConsistency := stw.subtaskCtx.Provider.EnsureChainConsistency(ctx, msgChainID)
		if errChainConsistency != nil {
			err = errors.Join(err, errChainConsistency)
		}
		_ = stw.SetStatus(ctx, database.SubtaskStatusWaiting)
		return fmt.Errorf("failed to perform agent chain for subtask %d: %w", subtaskID, err)
	}

	switch performResult {
	case providers.PerformResultWaiting:
		if err := stw.SetStatus(ctx, database.SubtaskStatusWaiting); err != nil {
			stw.handleInterrupting(err)
			return err
		}
	case providers.PerformResultDone:
		if err := stw.SetStatus(ctx, database.SubtaskStatusFinished); err != nil {
			stw.handleInterrupting(err)
			return fmt.Errorf("failed to set subtask %d status to finished: %w", subtaskID, err)
		}
	case providers.PerformResultError:
		if err := stw.SetStatus(ctx, database.SubtaskStatusFailed); err != nil {
			stw.handleInterrupting(err)
			return fmt.Errorf("failed to set subtask %d status to failed: %w", subtaskID, err)
		}

View on GitHub (pinned to ea665308ba)

Solutions

  1. Unwrap with errors.Is/errors.As: context.Canceled means the user/flow interrupted — no fix needed, subtask is already Waiting for resume; retry Run/PutInput later.
  2. For provider auth/quota errors, fix the API key or quota in Settings/env, then re-run the subtask (it stays Waiting).
  3. For network errors, verify egress connectivity/proxy settings to the LLM endpoint and retry.
  4. If errChainConsistency is joined in, reset the subtask's msgchain rows or recreate the subtask — the chain is too corrupted to resume.
  5. Check the specific LLM provider logs and tool container logs for the root cause before retrying.

Example fix

// before
if err := worker.Run(ctx); err != nil {
	return err
}
// after
if err := worker.Run(ctx); err != nil {
	switch {
	case errors.Is(err, context.Canceled):
		return nil // interrupted; subtask already reset to Waiting
	case errors.Is(err, context.DeadlineExceeded):
		return fmt.Errorf("chain timed out; retry with larger budget: %w", err)
	default:
		return err
	}
}
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-flight: live context and configured provider before running
if err := ctx.Err(); err != nil {
	return err
}
if apiKey == "" {
	return fmt.Errorf("LLM provider API key not configured")
}

Type guard

func classifyChainErr(err error) string {
	switch {
	case errors.Is(err, context.Canceled):
		return "interrupted"
	case errors.Is(err, context.DeadlineExceeded):
		return "timeout"
	case strings.Contains(err.Error(), "401"), strings.Contains(err.Error(), "quota"):
		return "provider-auth"
	default:
		return "transient"
	}
}

Try / catch

if err := worker.Run(ctx); err != nil {
	if strings.Contains(err.Error(), "failed to perform agent chain") {
		switch classifyChainErr(err) {
		case "interrupted":
			return nil // subtask reset to Waiting; resume later
		case "provider-auth":
			return fmt.Errorf("fix provider key/quota then re-run: %w", err)
		case "transient":
			// subtask is Waiting again; retry Run after backoff
		}
	}
	return err
}

Prevention

When it happens

Trigger: PerformAgentChain fails due to: LLM provider API error (invalid key, rate limit, timeout, context cancelled by flow interrupt), tool execution failure inside the Docker sandbox, DB failure while persisting chain messages, or EnsureChainConsistency failing during the post-error cleanup.

Common situations: Expired or quota-exhausted LLM API key; network egress blocked from the backend container to the LLM provider; user interrupted the flow cancelling ctx; tool container crashed mid-execution leaving the provider unable to complete the chain.

Related errors


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