plandex-ai/plandex · warning

No project ids provided

Error message

No project ids provided

What it means

ListPlansRunningHandler (plans_crud.go:417) returns 400 'No project ids provided' when the request has no projectId query parameters. Unlike ListPlansHandler (which returns an empty list), this handler requires at least one projectId because it lists currently running plans, so an empty filter is treated as a client error.

Source

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

	writePlans()
}

func ListPlansRunningHandler(w http.ResponseWriter, r *http.Request) {
	log.Println("Received request for ListPlansRunningHandler")
	auth := Authenticate(w, r, true)
	if auth == nil {
		return
	}

	projectIds := r.URL.Query()["projectId"]
	includeRecent := r.URL.Query().Get("recent") == "true"

	log.Println("projectIds: ", projectIds)

	if len(projectIds) == 0 {
		log.Println("No project ids provided")
		http.Error(w, "No project ids provided", http.StatusBadRequest)
		return
	}

	for _, projectId := range projectIds {
		if !authorizeProject(w, projectId, auth) {
			return
		}
	}

	plans, err := db.ListOwnedPlans(projectIds, auth.User.Id, false)

	if err != nil {
		log.Printf("Error listing plans: %v\n", err)
		http.Error(w, "Error listing plans: "+err.Error(), http.StatusInternalServerError)
		return
	}

	var planIds []string

View on GitHub (pinned to e2d772072e)

Solutions

  1. Add at least one projectId query parameter: GET .../plans/running?projectId=<id> (repeat the key for multiple projects).
  2. Check the client sends the exact parameter name 'projectId' (case-sensitive).
  3. If the value may be empty, omit the parameter or filter out empty strings client-side before the request.
  4. Ensure project IDs are loaded/fetched before calling this endpoint.

Example fix

// before
const url = `/api/plans/running?projectId=`; // empty value
// after
const ids = projectIds.filter(Boolean).map(id => `projectId=${encodeURIComponent(id)}`).join('&');
const url = `/api/plans/running?${ids}`;
Defensive patterns

Strategy: validation

Validate before calling

const ids = (projectIds || []).filter(Boolean);
if (ids.length === 0) throw new Error('At least one projectId is required for the running-plans endpoint');
const url = `/api/plans/running?${ids.map(id => `projectId=${encodeURIComponent(id)}`).join('&')}`;

Type guard

function hasProjectIds(params) {
  return Array.isArray(params.projectId) ? params.projectId.filter(Boolean).length > 0 : Boolean(params.projectId);
}

Try / catch

const res = await fetch(url);
if (res.status === 400 && (await res.text()).includes('No project ids provided')) {
  // caller bug: send at least one projectId before retrying
  return [];
}
if (!res.ok) throw new Error(`running plans request failed: ${res.status}`);

Prevention

When it happens

Trigger: GET the running-plans endpoint with no ?projectId=... parameter, an empty projectId value (e.g. ?projectId= yields no values via r.URL.Query()["projectId"] semantics), or a client sending the parameter under a misspelled/wrong key.

Common situations: Client code builds the URL without appending project IDs; a UI sends ?projectId= (empty value) instead of omitting it or repeating the key; SDK/client version mismatch changing the query parameter name.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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