plandex-ai/plandex · error

error getting plan subtasks: %v %s

Error message

error getting plan subtasks: %v
%s

What it means

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().

Source

Thrown at app/server/model/plan/tell_load.go:296

				err := <-innerErrCh
				if err != nil {
					errCh <- err
					return
				}
			}

			if promptMsg != nil {
				convo = append(convo, promptMsg)
			}

			errCh <- nil
		}()

		go func() {
			defer func() {
				if r := recover(); r != nil {
					log.Printf("panic in getPlanSubtasks: %v\n%s", r, debug.Stack())
					errCh <- fmt.Errorf("error getting plan subtasks: %v\n%s", r, debug.Stack())
					runtime.Goexit() // don't allow outer function to continue and double-send to channel
				}
			}()

			res, err := db.GetPlanSubtasks(auth.OrgId, planId)
			if err != nil {
				log.Printf("Error getting plan subtasks: %v\n", err)
				errCh <- fmt.Errorf("error getting plan subtasks: %v", err)
				return
			}
			subtasks = res
			errCh <- nil
		}()

		for i := 0; i < 4; i++ {
			err = <-errCh
			if err != nil {
				go notify.NotifyErr(notify.SeverityError, fmt.Errorf("error loading plan: %v", err))

View on GitHub (pinned to e2d772072e)

Solutions

  1. Read the appended stack trace in the error/log to find the panicking line
  2. Fix the nil/race condition indicated by the stack
  3. Ensure auth.OrgId and planId are validated non-empty before load
  4. Check for concurrent writes to shared state from the parallel loader goroutines

Example fix

// before
go func() {
    defer func() {
        if r := recover(); r != nil {
            errCh <- fmt.Errorf("error getting plan subtasks: %v\n%s", r, debug.Stack())
            runtime.Goexit()
        }
    }()
    res, err := db.GetPlanSubtasks(auth.OrgId, planId)
// after
if auth == nil || auth.OrgId == "" || planId == "" {
    errCh <- fmt.Errorf("invalid auth or planId for subtasks")
    return
}
go func() {
    defer func() {
        if r := recover(); r != nil {
            errCh <- fmt.Errorf("error getting plan subtasks: %v\n%s", r, debug.Stack())
            runtime.Goexit()
        }
    }()
    res, err := db.GetPlanSubtasks(auth.OrgId, planId)
Defensive patterns

Strategy: try-catch

Validate before calling

if auth == nil || auth.OrgId == "" || planId == "" {
    return fmt.Errorf("missing orgId or planId for subtask load")
}

Type guard

if db == nil {
    return fmt.Errorf("db handle not initialized")
}

Try / catch

defer func() {
    if r := recover(); r != nil {
        log.Printf("panic in getPlanSubtasks: %v\n%s", r, debug.Stack())
        errCh <- fmt.Errorf("error getting plan subtasks: %v\n%s", r, debug.Stack())
        runtime.Goexit()
    }
}()

Prevention

When it happens

Trigger: 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.

Common situations: Race on shared state during plan load, DB client initialized lazily and still nil, a driver bug triggered by malformed orgId/planId values.

Related errors


AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05). Data as JSON: /api/errors/03b6c4d8246d5fce. Report an issue: GitHub.