wavetermdev/waveterm · warning

method not allowed

Error message

method not allowed

What it means

handleRender only accepts POST; any other method returns HTTP 405 'method not allowed' (tsunami/engine/serverhandlers.go:112). The endpoint consumes a VDomFrontendUpdate JSON body, which only makes sense as a POST.

Source

Thrown at tsunami/engine/serverhandlers.go:112

	// Add fallback handler for embedded static files in production mode
	if opts.AssetsFS != nil {
		mux.HandleFunc("/", h.handleStaticFiles(opts.AssetsFS))
	}
}

func (h *httpHandlers) handleRender(w http.ResponseWriter, r *http.Request) {
	defer func() {
		panicErr := util.PanicHandler("handleRender", recover())
		if panicErr != nil {
			http.Error(w, fmt.Sprintf("internal server error: %v", panicErr), http.StatusInternalServerError)
		}
	}()

	setNoCacheHeaders(w)

	if r.Method != http.MethodPost {
		http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
		return
	}

	body, err := io.ReadAll(r.Body)
	if err != nil {
		http.Error(w, fmt.Sprintf("failed to read request body: %v", err), http.StatusBadRequest)
		return
	}

	var feUpdate rpctypes.VDomFrontendUpdate
	if err := json.Unmarshal(body, &feUpdate); err != nil {
		http.Error(w, fmt.Sprintf("failed to parse JSON: %v", err), http.StatusBadRequest)
		return
	}

	if feUpdate.ForceTakeover {
		h.Client.clientTakeover(feUpdate.ClientId)
	}

View on GitHub (pinned to a4447c1563)

Solutions

  1. Send the request as POST with a JSON VDomFrontendUpdate body.
  2. Fix the client call: fetch(url, {method: 'POST', headers: {'Content-Type': 'application/json'}, body: ...}).
  3. Point health checks or probes at a dedicated health route instead of the render endpoint.
  4. If GET rendering is needed, add an explicit GET handler rather than reusing this route.

Example fix

// before
await fetch(renderUrl) // GET

// after
await fetch(renderUrl, {method: "POST", headers: {"Content-Type": "application/json"}, body: JSON.stringify(feUpdate)})
Defensive patterns

Strategy: validation

Validate before calling

if (feUpdate === undefined) throw new Error("render endpoint requires POST with a JSON body");
const resp = await fetch(renderUrl, {method: "POST", headers: {"Content-Type": "application/json"}, body: JSON.stringify(feUpdate)});

Try / catch

const resp = await fetch(renderUrl, {method: "POST", body});
if (resp.status === 405) throw new Error("render endpoint only accepts POST");

Prevention

When it happens

Trigger: Issuing GET/PUT/DELETE/OPTIONS to the render endpoint — e.g. opening the URL in a browser (GET), a prefetch preflight, or a misconfigured fetch/axios call defaulting to GET.

Common situations: Testing the endpoint by pasting its URL in a browser, an API client wired to the wrong method, CORS preflight or health-check probes hitting the render route.

Related errors


AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01). Data as JSON: /api/errors/8a9f164c0ed1d2e9. Report an issue: GitHub.