plandex-ai/plandex · error

Error starting reply stream: %v

Error message

Error starting reply stream: %v

What it means

Thrown when model.CreateChatCompletionStream fails to open the streaming connection to the LLM provider. Any provider-side rejection — invalid API key, bad model name, network failure, quota exhaustion — surfaces here. The error is wrapped into an ApiError with the underlying message appended and sent on StreamDoneCh.

Source

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

	// output the modelReq to a json file
	// if jsonData, err := json.MarshalIndent(modelReq, "", "  "); err == nil {
	// 	timestamp := time.Now().Format("2006-01-02-150405")
	// 	filename := fmt.Sprintf("generations/model-request-%s.json", timestamp)
	// 	if err := os.WriteFile(filename, jsonData, 0644); err != nil {
	// 		log.Printf("Error writing model request to file: %v\n", err)
	// 	}
	// } else {
	// 	log.Printf("Error marshaling model request to JSON: %v\n", err)
	// }

	log.Printf("[Tell] doTellRequest retry=%d fallbackRetry=%d using model=%s",
		state.numErrorRetry, state.numFallbackRetry, baseModelConfig.ModelName)

	// start the stream
	stream, err := model.CreateChatCompletionStream(clients, authVars, modelConfig, state.settings, state.orgUserConfig, state.currentOrgId, state.currentUserId, active.ModelStreamCtx, modelReq)
	if err != nil {
		log.Printf("Error starting reply stream: %v\n", err)
		go notify.NotifyErr(notify.SeverityError, fmt.Errorf("error starting reply stream: %v", err))
		active.StreamDoneCh <- &shared.ApiError{
			Type:   shared.ApiErrorTypeOther,
			Status: http.StatusInternalServerError,
			Msg:    "Error starting reply stream: " + err.Error(),
		}
		return
	}

	// handle stream chunks
	go state.listenStream(stream)
}

func (state *activeTellStreamState) dryRunCalculateTokensWithoutContext(tentativeMaxTokens int, unfinishedSubtaskReasoning string) (bool, int) {
	clone := &activeTellStreamState{
		modelStreamId:       state.modelStreamId,
		clients:             state.clients,
		req:                 state.req,
		auth:                state.auth,

View on GitHub (pinned to e2d772072e)

Solutions

  1. Read the wrapped underlying error in the ApiError message to identify the provider cause
  2. Verify the provider API key/auth vars are valid and have quota
  3. Test network/proxy access to the provider endpoint from the server host
  4. Confirm the configured model name is still offered by the provider
  5. Retry after backoff if the provider reported 429/5xx

Example fix

// before
authVars["OPENAI_API_KEY"] = "" // rotated out
// after
authVars["OPENAI_API_KEY"] = os.Getenv("OPENAI_API_KEY") // valid key set before calling Tell
Defensive patterns

Strategy: retry

Validate before calling

// pre-flight provider auth check
if authVars[providerKeyEnv] == "" {
    return fmt.Errorf("%s is not set; cannot start stream", providerKeyEnv)
}

Try / catch

if apiErr := <-active.StreamDoneCh; apiErr != nil && strings.HasPrefix(apiErr.Msg, "Error starting reply stream:") {
    cause := strings.TrimPrefix(apiErr.Msg, "Error starting reply stream: ")
    if strings.Contains(cause, "429") || strings.Contains(cause, "timeout") {
        // retry with exponential backoff
    } else if strings.Contains(cause, "401") {
        // refresh API key
    }
}

Prevention

When it happens

Trigger: CreateChatCompletionStream returns a non-nil err: expired/invalid provider API key, unknown/disabled model for the account, provider outage, DNS/proxy failure, or malformed request built from the messages.

Common situations: Rotated or missing OPENAI_API_KEY / ANTHROPIC_API_KEY auth vars; provider rate-limit or account suspension; corporate proxy blocking api.openai.com; model deprecated by provider after an upgrade.

Related errors


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