jd-opensource/joyagent-jdgenie · error · IllegalStateException

A plan already exists. Delete the current plan first.

Error message

A plan already exists. Delete the current plan first.

What it means

PlanningTool holds a single current plan; createPlan throws IllegalStateException when a plan already exists and refuses to overwrite it. The existing plan must be deleted (or updated) before creating a new one.

Solutions

  1. Call command=delete before issuing another create
  2. Use the update command to modify the existing plan instead
  3. Check plan state (e.g. via a get/status command) before create

Example fix

// before
planningTool.execute(Map.of("command", "create", "title", t, "steps", s));
// after
planningTool.execute(Map.of("command", "delete"));
planningTool.execute(Map.of("command", "create", "title", t, "steps", s));
Defensive patterns

Strategy: try-catch

Validate before calling

// check whether a plan already exists via the tool before issuing create

Try / catch

try {
    return planningTool.execute(createParams);
} catch (IllegalStateException e) {
    if (e.getMessage().contains("plan already exists")) {
        planningTool.execute(Map.of("command", "delete"));
        return planningTool.execute(createParams);
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling command=create twice without an intervening delete/update of the plan.

Common situations: Agent retrying a create after a partial failure, LLM re-emitting a create command in a multi-turn loop, or not checking plan state before creating.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of jd-opensource/joyagent-jdgenie@2417e0b8b6 (2026-09-08). Data as JSON: /api/errors/4215869d0b4f605b. Report an issue: GitHub.

Appendix: source

Thrown at genie-backend/src/main/java/com/jd/genie/agent/tool/common/PlanningTool.java:149

        Function<Map<String, Object>, String> handler = commandHandlers.get(command);
        if (handler != null) {
            return handler.apply(params);
        } else {
            throw new IllegalArgumentException("Unknown command: " + command);
        }
    }

    private String createPlan(Map<String, Object> params) {
        String title = (String) params.get("title");
        List<String> steps = (List<String>) params.get("steps");

        if (title == null || steps == null) {
            throw new IllegalArgumentException("title, and steps are required for create command");
        }

        if (plan != null) {
            throw new IllegalStateException("A plan already exists. Delete the current plan first.");
        }

        plan = Plan.create(title, steps);
        return "我已创建plan";
    }

    private String updatePlan(Map<String, Object> params) {
        String title = (String) params.get("title");
        List<String> steps = (List<String>) params.get("steps");

        if (plan == null) {
            throw new IllegalStateException("No plan exists. Create a plan first.");
        }

        plan.update(title, steps);
        return "我已更新plan";
    }

View on GitHub (pinned to 2417e0b8b6)