plandex-ai/plandex · error

Prompt message isn't set

Error message

Prompt message isn't set

What it means

Thrown when the promptMessage produced by state.resolvePromptMessage is nil at the point where execTellPlan appends it to the messages slice. The library treats a nil prompt as an unrecoverable internal state bug — no user prompt can be sent to the LLM — so it reports the error, sends a 500 ApiError on StreamDoneCh, and returns.

Source

Thrown at app/server/model/plan/tell_exec.go:362

		active.StreamDoneCh <- &shared.ApiError{
			Type:   shared.ApiErrorTypeOther,
			Status: http.StatusInternalServerError,
			Msg:    "Token limit exceeded before adding conversation",
		}
		return
	}

	if !state.addConversationMessages() {
		return
	}

	// add the prompt message to the end of the messages slice
	if promptMessage != nil {
		state.messages = append(state.messages, *promptMessage)
	} else {
		log.Println("promptMessage is nil")
		go notify.NotifyErr(notify.SeverityError, fmt.Errorf("promptMessage is nil"))

		active.StreamDoneCh <- &shared.ApiError{
			Type:   shared.ApiErrorTypeOther,
			Status: http.StatusInternalServerError,
			Msg:    "Prompt message isn't set",
		}
		return
	}

	state.replyId = uuid.New().String()
	state.replyParser = types.NewReplyParser()

	if missingFileResponse != "" && !state.handleMissingFileResponse(unfinishedSubtaskReasoning) {
		return
	}

	// filter out any messages that are empty
	state.messages = model.FilterEmptyMessages(state.messages)

View on GitHub (pinned to e2d772072e)

Solutions

  1. Re-send the tell request with a non-empty prompt
  2. Check resolvePromptMessage logic for branches that can return ok=true with a nil message
  3. Upgrade/patch the plan model code where the nil check happens too late (after token estimation uses *promptMessage)
  4. Report to maintainers with server logs if prompt was non-empty

Example fix

// before
promptMessage, ok := state.resolvePromptMessage(unfinishedSubtaskReasoning)
if !ok { return }
// after: fail fast with a clear message before using it
promptMessage, ok := state.resolvePromptMessage(unfinishedSubtaskReasoning)
if !ok || promptMessage == nil {
    active.StreamDoneCh <- &shared.ApiError{Type: shared.ApiErrorTypeOther, Status: http.StatusBadRequest, Msg: "prompt is empty"}
    return
}
Defensive patterns

Strategy: validation

Validate before calling

if strings.TrimSpace(prompt) == "" {
    return errors.New("prompt must be a non-empty string before calling Tell")
}

Try / catch

if apiErr := <-active.StreamDoneCh; apiErr != nil && strings.Contains(apiErr.Msg, "Prompt message isn't set") {
    // resend with a valid non-empty prompt
}

Prevention

When it happens

Trigger: resolvePromptMessage returned ok=true earlier but produced a nil message (e.g. empty prompt input or an internal branch that fails to build the ExtendedChatMessage), or the prompt message pointer was invalidated between resolution and use.

Common situations: Sending a tell request with empty/whitespace-only prompt text; internal refactors changing resolvePromptMessage semantics; race where the prompt is cleared mid-request.

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/449a9a5f579752ac. Report an issue: GitHub.