{"record":{"id":"7d9ddedd8cf8e9da","repo":"vxcontrol/pentagi","slug":"subtask-d-has-created-yet-w","errorCode":null,"errorMessage":"subtask %d has created yet: %w","messagePattern":"subtask (.+?) has created yet: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"backend/pkg/controller/subtask.go","lineNumber":107,"sourceCode":"\tvar completed, waiting bool\n\tswitch subtask.Status {\n\tcase database.SubtaskStatusFinished, database.SubtaskStatusFailed:\n\t\tcompleted = true\n\tcase database.SubtaskStatusWaiting:\n\t\twaiting = true\n\tcase database.SubtaskStatusRunning:\n\t\tvar err error\n\t\t// if subtask is running, it means that it was not finished by previous run\n\t\t// so we need to set it to created and continue from the beginning\n\t\tsubtask, err = taskCtx.DB.UpdateSubtaskStatus(ctx, database.UpdateSubtaskStatusParams{\n\t\t\tStatus: database.SubtaskStatusCreated,\n\t\t\tID:     subtask.ID,\n\t\t})\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to update subtask %d status to created: %w\", subtask.ID, err)\n\t\t}\n\tcase database.SubtaskStatusCreated:\n\t\treturn nil, fmt.Errorf(\"subtask %d has created yet: %w\", subtask.ID, ErrNothingToLoad)\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"unexpected subtask status: %s\", subtask.Status)\n\t}\n\n\tmsgChains, err := taskCtx.DB.GetSubtaskPrimaryMsgChains(ctx, database.Int64ToNullInt64(&subtask.ID))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get subtask primary msg chains for subtask %d: %w\", subtask.ID, err)\n\t}\n\n\tif len(msgChains) == 0 {\n\t\treturn nil, fmt.Errorf(\"subtask %d has no msg chains: %w\", subtask.ID, ErrNothingToLoad)\n\t}\n\n\treturn &subtaskWorker{\n\t\tmx: &sync.RWMutex{},\n\t\tsubtaskCtx: &SubtaskContext{\n\t\t\tMsgChainID:         msgChains[0].ID,\n\t\t\tSubtaskID:          subtask.ID,","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/controller/subtask.go#L89-L125","documentation":"LoadSubtaskWorker returns this error (wrapping ErrNothingToLoad) when the subtask's persisted status is already SubtaskStatusCreated — meaning it was created but never advanced, so there is nothing new to load or resume. It is a sentinel-style condition, not an unexpected failure.","triggerScenarios":"LoadSubtasks encounters a subtask whose DB status is exactly 'created': a subtask was inserted but its worker never started, or a prior load attempt already reset it and no progress was made.","commonSituations":"Recovery scan after a crash finds freshly-created-but-never-run subtasks; double invocation of LoadSubtasks for the same subtask; a producer inserted the subtask row but crashed before starting the worker.","solutions":["Check errors.Is(err, ErrNothingToLoad) and skip the subtask or start it from scratch rather than treating it as a hard failure.","If the subtask should run, kick off its worker for the 'created' state instead of calling the load path again.","Deduplicate LoadSubtasks calls so the same subtask is not loaded twice in one recovery pass.","Audit the code path that creates subtasks to ensure workers are started immediately after insertion."],"exampleFix":"// before\nworker, err := LoadSubtaskWorker(ctx, taskCtx, subtask)\nif err != nil {\n    return err\n}\n// after\nworker, err := LoadSubtaskWorker(ctx, taskCtx, subtask)\nif err != nil {\n    if errors.Is(err, ErrNothingToLoad) {\n        return nil // nothing to resume; skip\n    }\n    return err\n}","handlingStrategy":"type-guard","validationCode":"// skip subtasks already in created state before attempting load\nif subtask.Status == database.SubtaskStatusCreated {\n    return nil // nothing to load\n}","typeGuard":"func IsNothingToLoad(err error) bool {\n    return errors.Is(err, controller.ErrNothingToLoad)\n}","tryCatchPattern":"worker, err := LoadSubtaskWorker(ctx, taskCtx, subtask)\nif err != nil {\n    if errors.Is(err, controller.ErrNothingToLoad) {\n        log.Info(\"subtask already created, skipping\", \"id\", subtask.ID)\n        return nil\n    }\n    return err\n}","preventionTips":["Always errors.Is against ErrNothingToLoad; it is an expected condition, not a bug.","Deduplicate recovery passes so a subtask is loaded once per cycle.","Start a subtask's worker immediately after creating its row.","Track created-but-never-run subtasks with a metric/alert."],"tags":["state-machine","subtask","nothing-to-load"],"backgroundTag":"invalid-state-transition","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}