juanfont/headscale · warning

ErrMissingURLParameter

ErrMissingURLParameter

Error message

missing URL parameter: %s

What it means

Returned by stringParam when a chi URL parameter the handler expects is empty. This helper backs most noise-router handlers, so the named key in the message tells you which route parameter was missing (e.g. node, user, key).

Solutions

  1. Check the error's parameter name and the route pattern in hscontrol/noise.go's router setup
  2. Fix the caller to include the non-empty parameter in the URL path
  3. If writing integrations, build URLs with the exact route templates the router registers
Defensive patterns

Strategy: validation

Validate before calling

if nodeKey := chi.URLParam(req, "node"); nodeKey == "" {
    return errors.New("required URL parameter 'node' is missing")
}

Try / catch

if _, err := stringParam(req, "key"); err != nil {
    if errors.Is(err, ErrMissingURLParameter) {
        // caller built a malformed URL; log the route and retry with corrected path
    }
}

Prevention

When it happens

Trigger: A Noise API request to a route whose pattern requires a parameter, but the request path omitted it — e.g. /machine/ without the id segment, or a client constructing URLs by string concatenation with an empty value.

Common situations: Custom automation hitting the Noise API with malformed paths; client-side bugs building request URLs; route table changes where a parameter was renamed.

Related errors


AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15). Data as JSON: /api/errors/5aef7ab31d813569. Report an issue: GitHub.

Appendix: source

Thrown at hscontrol/noise.go:341

	}

	pingID := req.URL.Query().Get("id")
	if pingID == "" {
		http.Error(writer, "missing ping ID", http.StatusBadRequest)
		return
	}

	if h.state.CompletePing(pingID) {
		writer.WriteHeader(http.StatusOK)
	} else {
		http.Error(writer, "unknown or expired ping", http.StatusNotFound)
	}
}

func stringParam(req *http.Request, key string) (string, error) {
	param := chi.URLParam(req, key)
	if param == "" {
		return "", fmt.Errorf("%w: %s", ErrMissingURLParameter, key)
	}

	return param, nil
}

func nodeIDParam(req *http.Request, key string) (types.NodeID, error) {
	param := chi.URLParam(req, key)
	if param == "" {
		return 0, fmt.Errorf("%w: %s", ErrMissingURLParameter, key)
	}

	id, err := types.ParseNodeID(param)
	if err != nil {
		return 0, fmt.Errorf("parsing %s: %w", key, err)
	}

	return id, nil
}

View on GitHub (pinned to 565fd254d0)