plandex-ai/plandex · error

err.Error()

Error message

err.Error()

What it means

This is a generic 500 returned by ListPlansRunningHandler when one of two parallel goroutines fails: either fetching active/recent model streams (GetActiveOrRecentModelStreams / GetActiveModelStreams) or fetching branches (ListBranchesForPlans). The handler collects results over an errCh channel and surfaces the first non-nil error verbatim to the client. The message text is the wrapped Go error, so it will name the failing DB query (e.g. 'error getting recent model streams: ...' or 'error getting branches: ...'), or a panic recovered inside a goroutine.

Source

Thrown at app/server/handlers/plans_crud.go:487

				log.Printf("panic in ListPlansRunningHandler: %v\n%s", r, debug.Stack())
				errCh <- fmt.Errorf("panic in ListPlansRunningHandler: %v\n%s", r, debug.Stack())
				runtime.Goexit() // don't allow outer function to continue and double-send to channel
			}
		}()
		var err error
		branches, err = db.ListBranchesForPlans(auth.OrgId, planIds)
		if err != nil {
			errCh <- fmt.Errorf("error getting branches: %v", err)
			return
		}
		errCh <- nil
	}()

	for i := 0; i < 2; i++ {
		err := <-errCh
		if err != nil {
			log.Println(err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
	}

	res := shared.ListPlansRunningResponse{
		Branches:                   []*shared.Branch{},
		StreamStartedAtByBranchId:  map[string]time.Time{},
		StreamFinishedAtByBranchId: map[string]time.Time{},
		PlansById:                  map[string]*shared.Plan{},
		StreamIdByBranchId:         map[string]string{},
	}

	var apiPlansById = make(map[string]*shared.Plan)
	for _, plan := range plans {
		apiPlan := plan.ToApi()
		apiPlansById[plan.Id] = apiPlan
	}

View on GitHub (pinned to e2d772072e)

Solutions

  1. Read the server log line printed just before the response (log.Println(err)) — it contains the underlying database error; fix the root cause there
  2. Check DB connectivity/health (pool exhaustion, max_connections, timeouts) and retry the request
  3. If a panic was logged with a stack trace, fix the nil-dereference or bug in the goroutine that panicked
  4. If it persists, verify the DB schema matches the sqlx struct tags for ModelStream and Branch after recent migrations
Defensive patterns

Strategy: retry

Validate before calling

// Pre-flight DB health check before calling the endpoint
if err := db.Conn.Ping(); err != nil {
    return fmt.Errorf("database unavailable: %w", err)
}

Try / catch

// Go: check status and error body, retry transient failures with backoff
resp, err := client.Get(listPlansRunningURL)
if err != nil { return err }
if resp.StatusCode == http.StatusInternalServerError {
    body, _ := io.ReadAll(resp.Body)
    return retryWithBackoff(3, func() error { return callListPlansRunning() })
}

Prevention

When it happens

Trigger: Calling GET list-plans-running while the database query for streams or branches fails (connection drop, timeout, bad SQL, transient Postgres error), or one of the goroutines panics (nil deref, etc.) and the deferred recover sends a wrapped panic error to errCh.

Common situations: Postgres restarts or connection-pool exhaustion under load; slow queries hitting a statement timeout; schema drift after a migration making ListBranchesForPlans fail; a bug causing a nil-pointer panic inside one of the goroutines.

Understand the failure class

Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.

Related errors


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