plandex-ai/plandex · error

Not found

Error message

Not found

What it means

The archive UPDATE ran without error but affected 0 rows, meaning no plan with the given planId existed at UPDATE time; the handler returns HTTP 404 'Not found'. This is a race/consistency check after the state guard passed.

Source

Thrown at app/server/handlers/plans_changes.go:473

	res, err := db.Conn.Exec("UPDATE plans SET archived_at = NOW() WHERE id = $1", planId)

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

	rowsAffected, err := res.RowsAffected()
	if err != nil {
		log.Printf("Error getting rows affected: %v\n", err)
		http.Error(w, "Error getting rows affected: "+err.Error(), http.StatusInternalServerError)
		return
	}

	if rowsAffected == 0 {
		log.Println("Plan not found")
		http.Error(w, "Not found", http.StatusNotFound)
		return
	}

	log.Println("Successfully archived plan", planId)
}

func UnarchivePlanHandler(w http.ResponseWriter, r *http.Request) {
	auth := Authenticate(w, r, true)
	if auth == nil {
		return
	}

	log.Println("Received request for UnarchivePlanHandler")

	vars := mux.Vars(r)
	planId := vars["planId"]
	log.Println("planId: ", planId)

View on GitHub (pinned to e2d772072e)

Solutions

  1. Verify the planId exists (query plans by id) in the environment you're hitting
  2. Re-fetch the plan list and retry with a fresh planId
  3. Check you're pointed at the intended database/environment
  4. Handle 404 in the client by refreshing plan state rather than retrying

Example fix

// before
await archivePlan('abc123'); // stale id → 404
// after
const plans = await listPlans();
if (plans.some(p => p.id === id)) await archivePlan(id); else refreshList();
Defensive patterns

Strategy: validation

Validate before calling

const plans = await listPlans();
if (!plans.some(p => p.id === planId)) throw new Error(`Plan ${planId} does not exist`);
await archivePlan(planId);

Type guard

function planExists(plans, id) { return Array.isArray(plans) && plans.some(p => p && p.id === id); }

Try / catch

try { await archivePlan(planId); } catch (e) { if (e.status === 404) { await refreshPlans(); throw new Error('Plan not found — it may have been deleted'); } throw e; }

Prevention

When it happens

Trigger: planId in the URL doesn't match any row in plans (typo, wrong environment, plan deleted between the authorizePlanArchive SELECT and the UPDATE, or the plan was removed by a concurrent operation).

Common situations: Client caching a stale planId after the plan was deleted; archiving against the wrong database/environment (staging vs prod); race with a delete operation; user following an outdated link.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — 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/1ad057a4af1572ab. Report an issue: GitHub.