{"record":{"id":"cd89bcd0000f79e0","repo":"vxcontrol/pentagi","slug":"failed-to-create-subtask-for-task-d-w","errorCode":null,"errorMessage":"failed to create subtask for task %d: %w","messagePattern":"failed to create subtask for task (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/pkg/controller/subtasks.go","lineNumber":90,"sourceCode":"\tplan, err := stc.taskCtx.Provider.GenerateSubtasks(ctx, stc.taskCtx.TaskID)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to generate subtasks for task %d: %w\", stc.taskCtx.TaskID, err)\n\t}\n\n\tif len(plan) == 0 {\n\t\treturn fmt.Errorf(\"no subtasks generated for task %d\", stc.taskCtx.TaskID)\n\t}\n\n\t// TODO: change it to insert subtasks in transaction\n\tfor _, info := range plan {\n\t\t_, err := stc.taskCtx.DB.CreateSubtask(ctx, database.CreateSubtaskParams{\n\t\t\tStatus:      database.SubtaskStatusCreated,\n\t\t\tTaskID:      stc.taskCtx.TaskID,\n\t\t\tTitle:       info.Title,\n\t\t\tDescription: info.Description,\n\t\t})\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to create subtask for task %d: %w\", stc.taskCtx.TaskID, err)\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (stc *subtaskController) RefineSubtasks(ctx context.Context) error {\n\tsubtasks, err := stc.taskCtx.DB.GetTaskSubtasks(ctx, stc.taskCtx.TaskID)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to get task %d subtasks: %w\", stc.taskCtx.TaskID, err)\n\t}\n\n\tplan, err := stc.taskCtx.Provider.RefineSubtasks(ctx, stc.taskCtx.TaskID)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to refine subtasks for task %d: %w\", stc.taskCtx.TaskID, err)\n\t}\n\n\tif len(plan) == 0 {","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/controller/subtasks.go#L72-L108","documentation":"Wraps the error from DB.CreateSubtask while persisting each subtask from a generated plan. The plan was produced successfully but writing a subtask row to PostgreSQL failed, aborting generation partway (creation is not transactional — see the TODO in the source). Some subtasks may already have been created, so the task can be left with a partial plan.","triggerScenarios":"In GenerateSubtasks' loop, stc.taskCtx.DB.CreateSubtask(ctx, CreateSubtaskParams{...}) fails for one of the plan entries — DB connection loss, context cancellation mid-loop, unique constraint violation, or schema mismatch.","commonSituations":"DB restart or connection pool exhaustion mid-loop; the caller's context canceled halfway through inserting the plan; migration drift making CreateSubtaskParams incompatible with the table; long plans hitting a statement timeout.","solutions":["Inspect the wrapped error; if transient (connection/context), retry GenerateSubtasks — but first check for a partial plan already in the DB to avoid duplicates.","Check errors.Is(err, context.Canceled): the caller canceled during insertion; the partially created subtasks remain and can be loaded with LoadSubtasks.","Verify the subtasks schema is up to date (goose migrations) so CreateSubtaskParams matches the table.","If duplicates from partial inserts are the issue, delete the task's subtasks before regenerating.","Contribute/apply the transactional insert (the TODO) so plan creation is all-or-nothing."],"exampleFix":"// before: partial inserts possible\nfor _, info := range plan {\n    _, err := stc.taskCtx.DB.CreateSubtask(ctx, params)\n    if err != nil {\n        return fmt.Errorf(\"failed to create subtask for task %d: %w\", taskID, err)\n    }\n}\n// after: check for existing partial plan before regenerating\nexisting, _ := stc.taskCtx.DB.GetTaskSubtasks(ctx, taskID)\nif len(existing) > 0 {\n    return nil // plan partially created; resume instead of duplicating\n}","handlingStrategy":"try-catch","validationCode":"if ctx.Err() != nil { return ctx.Err() }\nif err := db.PingContext(ctx); err != nil { return err }\n// avoid duplicating a partial plan\nexisting, _ := db.GetTaskSubtasks(ctx, taskID)\nif len(existing) > 0 { return ErrPlanExists }","typeGuard":"func isTransientInsertError(err error) bool {\n    var pgErr *pgconn.PgError\n    return errors.As(err, &pgErr) &&\n        (pgErr.Code == \"08000\" || pgErr.Code == \"08006\" || pgErr.Code == \"40001\")\n}","tryCatchPattern":"if err := stc.GenerateSubtasks(ctx); err != nil {\n    if strings.Contains(err.Error(), \"failed to create subtask\") {\n        // partial plan may exist: inspect DB and clean up or resume\n        logrus.WithError(err).WithField(\"task_id\", taskID).Error(\"partial subtask insert\")\n        return stc.reconcilePartialPlan(ctx, taskID)\n    }\n    return err\n}","preventionTips":["Check for existing subtasks before regenerating a plan to avoid duplicates from partial inserts.","Keep DB connections healthy — monitor pool saturation during plan generation.","Make subtask insertion transactional (all plan rows or none) to eliminate partial plans.","Run migrations so CreateSubtaskParams always matches the table schema."],"tags":["database","subtask","persistence","partial-failure"],"backgroundTag":"database-insert-failed","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}