{"record":{"id":"03b6c4d8246d5fce","repo":"plandex-ai/plandex","slug":"error-getting-plan-subtasks-v-s","errorCode":null,"errorMessage":"error getting plan subtasks: %v\n%s","messagePattern":"error getting plan subtasks: (.+?)\n(.+?)","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"app/server/model/plan/tell_load.go","lineNumber":296,"sourceCode":"\t\t\t\terr := <-innerErrCh\n\t\t\t\tif err != nil {\n\t\t\t\t\terrCh <- err\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif promptMsg != nil {\n\t\t\t\tconvo = append(convo, promptMsg)\n\t\t\t}\n\n\t\t\terrCh <- nil\n\t\t}()\n\n\t\tgo func() {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tlog.Printf(\"panic in getPlanSubtasks: %v\\n%s\", r, debug.Stack())\n\t\t\t\t\terrCh <- fmt.Errorf(\"error getting plan subtasks: %v\\n%s\", r, debug.Stack())\n\t\t\t\t\truntime.Goexit() // don't allow outer function to continue and double-send to channel\n\t\t\t\t}\n\t\t\t}()\n\n\t\t\tres, err := db.GetPlanSubtasks(auth.OrgId, planId)\n\t\t\tif err != nil {\n\t\t\t\tlog.Printf(\"Error getting plan subtasks: %v\\n\", err)\n\t\t\t\terrCh <- fmt.Errorf(\"error getting plan subtasks: %v\", err)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tsubtasks = res\n\t\t\terrCh <- nil\n\t\t}()\n\n\t\tfor i := 0; i < 4; i++ {\n\t\t\terr = <-errCh\n\t\t\tif err != nil {\n\t\t\t\tgo notify.NotifyErr(notify.SeverityError, fmt.Errorf(\"error loading plan: %v\", err))","sourceCodeStart":278,"sourceCodeEnd":314,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/model/plan/tell_load.go#L278-L314","documentation":"This error is the panic-recovery path of the goroutine that calls db.GetPlanSubtasks(auth.OrgId, planId) in tell_load.go. If the goroutine panics (nil pointer, index out of range, nil DB handle), the deferred recover() logs the stack and sends 'error getting plan subtasks: <panic>\\n<stack trace>' to errCh. Unlike the non-panic variant (index 742), it includes the full debug.Stack().","triggerScenarios":"A runtime panic inside the getPlanSubtasks goroutine: nil auth or db handle, nil map access while building subtask results, or a panic propagated from the DB driver layer.","commonSituations":"Race on shared state during plan load, DB client initialized lazily and still nil, a driver bug triggered by malformed orgId/planId values.","solutions":["Read the appended stack trace in the error/log to find the panicking line","Fix the nil/race condition indicated by the stack","Ensure auth.OrgId and planId are validated non-empty before load","Check for concurrent writes to shared state from the parallel loader goroutines"],"exampleFix":"// before\ngo func() {\n    defer func() {\n        if r := recover(); r != nil {\n            errCh <- fmt.Errorf(\"error getting plan subtasks: %v\\n%s\", r, debug.Stack())\n            runtime.Goexit()\n        }\n    }()\n    res, err := db.GetPlanSubtasks(auth.OrgId, planId)\n// after\nif auth == nil || auth.OrgId == \"\" || planId == \"\" {\n    errCh <- fmt.Errorf(\"invalid auth or planId for subtasks\")\n    return\n}\ngo func() {\n    defer func() {\n        if r := recover(); r != nil {\n            errCh <- fmt.Errorf(\"error getting plan subtasks: %v\\n%s\", r, debug.Stack())\n            runtime.Goexit()\n        }\n    }()\n    res, err := db.GetPlanSubtasks(auth.OrgId, planId)","handlingStrategy":"try-catch","validationCode":"if auth == nil || auth.OrgId == \"\" || planId == \"\" {\n    return fmt.Errorf(\"missing orgId or planId for subtask load\")\n}","typeGuard":"if db == nil {\n    return fmt.Errorf(\"db handle not initialized\")\n}","tryCatchPattern":"defer func() {\n    if r := recover(); r != nil {\n        log.Printf(\"panic in getPlanSubtasks: %v\\n%s\", r, debug.Stack())\n        errCh <- fmt.Errorf(\"error getting plan subtasks: %v\\n%s\", r, debug.Stack())\n        runtime.Goexit()\n    }\n}()","preventionTips":["Keep goroutines free of shared mutable state or guard it with mutexes","Always recover in loader goroutines and send the error on the channel","Initialize DB clients before spawning loaders","Audit nil-dereference risks in result-mapping code"],"tags":["panic","concurrency","database","goroutine","stack-trace"],"backgroundTag":"goroutine-panic-recovered","analyzedSha":"e2d772072efadbe41d2946d97d79be55532dbab5","analyzedAt":"2026-09-05T20:56:53.631Z","contentChangedAt":"2026-09-05T20:56:53.631Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}