ory/hydra · error

Failed to create request: %s

Error message

Failed to create request: %s

What it means

Returned when http.NewRequestWithContext fails to construct the PUT request to the Hydra admin device-accept URL. NewRequestWithContext only errors on an invalid method or an unparseable URL, so this almost always means acceptURL is malformed. The handler responds with a 500 containing the parse error.

Source

Thrown at cmd/cmd_perform_device_flow.go:206

	// Accept the user code with a hand-rolled request instead of the generated
	// client: other modules in this repository compile this package against the
	// released hydra-client-go/v2 module, which predates the device
	// authorization API.
	cfg := s.cl.GetConfig()
	if len(cfg.Servers) == 0 {
		http.Error(w, "No Hydra endpoint is configured", http.StatusInternalServerError)
		return
	}
	acceptURL := strings.TrimSuffix(cfg.Servers[0].URL, "/") +
		"/admin/oauth2/auth/requests/device/accept?device_challenge=" + url.QueryEscape(challenge)
	body, err := json.Marshal(map[string]string{"user_code": userCode})
	if err != nil {
		http.Error(w, fmt.Sprintf("Failed to encode request body: %s", err), http.StatusInternalServerError)
		return
	}
	req, err := http.NewRequestWithContext(r.Context(), http.MethodPut, acceptURL, bytes.NewReader(body))
	if err != nil {
		http.Error(w, fmt.Sprintf("Failed to create request: %s", err), http.StatusInternalServerError)
		return
	}
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Accept", "application/json")

	hc := cfg.HTTPClient
	if hc == nil {
		hc = http.DefaultClient
	}
	res, err := hc.Do(req)
	if err != nil {
		http.Error(w, fmt.Sprintf("Failed to accept user code request: %s", err), http.StatusInternalServerError)
		return
	}
	defer res.Body.Close() //nolint:errcheck
	raw, err := io.ReadAll(io.LimitReader(res.Body, 1<<20))
	if err != nil {
		http.Error(w, fmt.Sprintf("Failed to read response: %s", err), http.StatusInternalServerError)

View on GitHub (pinned to 4174065ffb)

Solutions

  1. Print/validate cfg.Servers[0].URL before building acceptURL; run it through url.Parse and fail fast with a clear config error.
  2. Normalize the config value: strings.TrimSpace and reject values that do not start with http:// or https://.
  3. Since the device_challenge is already url.QueryEscape'd, ensure no double-escaping or manual concatenation of raw query strings; build with url.Values instead.

Example fix

// before
acceptURL := strings.TrimSuffix(cfg.Servers[0].URL, "/") +
	"/admin/oauth2/auth/requests/device/accept?device_challenge=" + url.QueryEscape(challenge)
// after
base, err := url.Parse(strings.TrimSpace(cfg.Servers[0].URL))
if err != nil {
	http.Error(w, "Invalid server URL in configuration", http.StatusInternalServerError)
	return
}
base.Path = strings.TrimSuffix(base.Path, "/") + "/admin/oauth2/auth/requests/device/accept"
q := base.Query(); q.Set("device_challenge", challenge); base.RawQuery = q.Encode()
acceptURL := base.String()
Defensive patterns

Strategy: validation

Validate before calling

u, err := url.Parse(cfg.Servers[0].URL)
if err != nil || (u.Scheme != "http" && u.Scheme != "https") || u.Host == "" {
	return fmt.Errorf("invalid server URL in config: %q", cfg.Servers[0].URL)
}

Type guard

func isValidHTTPURL(s string) bool {
	u, err := url.Parse(strings.TrimSpace(s))
	return err == nil && (u.Scheme == "http" || u.Scheme == "https") && u.Host != ""
}

Try / catch

req, err := http.NewRequestWithContext(ctx, http.MethodPut, acceptURL, body)
if err != nil {
	log.Printf("bad request URL %q: %v", acceptURL, err)
	http.Error(w, "invalid admin URL", http.StatusInternalServerError)
	return
}

Prevention

When it happens

Trigger: url.Parse inside http.NewRequestWithContext fails on acceptURL built as cfg.Servers[0].URL + "/admin/oauth2/auth/requests/device/accept?device_challenge=" + query-escaped challenge. This happens when cfg.Servers[0].URL contains invalid characters, control characters, whitespace, or is empty/garbage (bad config).

Common situations: Misconfigured server URL in the Hydra/ory CLI config (trailing garbage, embedded spaces or newlines from env vars), empty Servers array handled elsewhere but a server entry with a malformed URL, or copy-pasted URLs with invisible characters.

Understand the failure class

Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.

Related errors


AI-assisted analysis of ory/hydra@4174065ffb (2026-09-03). Data as JSON: /api/errors/aaf905ab4a8bf47f. Report an issue: GitHub.