vxcontrol/pentagi · error

failed to create subtask worker: %w

Error message

failed to create subtask worker: %w

What it means

Wraps any error from LoadSubtaskWorker while restoring individual subtask workers during LoadSubtasks, excluding ErrNothingToLoad which is skipped (continue). It means a persisted subtask could not be reconstructed into a runnable worker — e.g. its provider/chain state is invalid.

Source

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

	defer stc.mx.Unlock()

	subtasks, err := stc.taskCtx.DB.GetTaskSubtasks(ctx, taskID)
	if err != nil {
		return fmt.Errorf("failed to get subtasks for task %d: %w", taskID, err)
	}

	if len(subtasks) == 0 {
		return fmt.Errorf("no subtasks found for task %d: %w", taskID, ErrNothingToLoad)
	}

	for _, subtask := range subtasks {
		st, err := LoadSubtaskWorker(ctx, subtask, stc.taskCtx, updater)
		if err != nil {
			if errors.Is(err, ErrNothingToLoad) {
				continue
			}

			return fmt.Errorf("failed to create subtask worker: %w", err)
		}

		stc.subtasks[subtask.ID] = st
	}

	return nil
}

func (stc *subtaskController) GenerateSubtasks(ctx context.Context) error {
	plan, err := stc.taskCtx.Provider.GenerateSubtasks(ctx, stc.taskCtx.TaskID)
	if err != nil {
		return fmt.Errorf("failed to generate subtasks for task %d: %w", stc.taskCtx.TaskID, err)
	}

	if len(plan) == 0 {
		return fmt.Errorf("no subtasks generated for task %d", stc.taskCtx.TaskID)
	}

View on GitHub (pinned to ea665308ba)

Solutions

  1. Unwrap the error to find which subtask failed; inspect that subtask row's msg_chain_id/provider references for dangling data.
  2. Ensure all providers referenced by existing subtasks are still configured (env vars / settings) after config changes.
  3. If only one subtask is corrupt, delete or reset that row to 'created' and reload instead of failing the whole task load.
  4. Run pending DB migrations — schema drift between restarts breaks worker reconstruction.

Example fix

// before: fail entire load on first bad subtask
if err := st.LoadSubtasks(ctx, taskID, updater); err != nil {
    return err
}
// after: log and continue with healthy subtasks
if err := stc.LoadSubtasks(ctx, taskID, updater); err != nil {
    if errors.Is(err, ErrNothingToLoad) { /* handled inside */ }
    logrus.WithError(err).WithField("task_id", taskID).Warn("partial subtask load failure")
}
Defensive patterns

Strategy: try-catch

Validate before calling

// before loading, ensure every subtask's provider is still configured
cfg, err := settings.GetProviderConfig(ctx)
if err != nil || !cfg.Valid() {
    return fmt.Errorf("provider config missing, cannot load subtask workers")
}

Type guard

func isWorkerInitError(err error) bool {
    return err != nil && !errors.Is(err, ErrNothingToLoad) &&
        strings.Contains(err.Error(), "failed to create subtask worker")
}

Try / catch

if err := stc.LoadSubtasks(ctx, taskID, updater); err != nil {
    logrus.WithError(err).WithField("task_id", taskID).
        Error("subtask worker load failed — inspect dangling subtask rows")
    return err
}

Prevention

When it happens

Trigger: Inside LoadSubtasks' loop over fetched subtasks, LoadSubtaskWorker(ctx, subtask, taskCtx, updater) returns a non-ErrNothingToLoad error for some subtask.ID — bad message-chain reference, provider initialization failure, or missing updater state.

Common situations: DB rows referencing deleted message chains or providers after config/provider changes between restarts; a corrupted subtask row from an interrupted write; custom provider no longer configured so its worker can't be built.

Related errors


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