charmbracelet/crush · error
create request: %w
Error message
create request: %w
What it means
InitiateDeviceAuth builds the HTTP POST to the Hyper OAuth device endpoint with a JSON body containing the device name. If http.NewRequestWithContext itself fails (malformed URL or invalid reader), the error is wrapped as "create request". This is a construction-time failure — no network I/O has happened yet.
Source
Thrown at internal/oauth/hyper/device.go:48
type TokenResponse struct {
RefreshToken string `json:"refresh_token,omitempty"`
UserID string `json:"user_id"`
OrganizationID string `json:"organization_id"`
OrganizationName string `json:"organization_name"`
Error string `json:"error,omitempty"`
ErrorDescription string `json:"error_description,omitempty"`
}
// InitiateDeviceAuth calls the /device/auth endpoint to start the device flow.
func InitiateDeviceAuth(ctx context.Context) (*DeviceAuthResponse, error) {
url := hyper.BaseURL() + "/device/auth"
req, err := http.NewRequestWithContext(
ctx, http.MethodPost, url,
strings.NewReader(fmt.Sprintf(`{"device_name":%q}`, deviceName())),
)
if err != nil {
return nil, fmt.Errorf("create request: %w", err)
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("User-Agent", "crush")
client := &http.Client{Timeout: 30 * time.Second}
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("execute request: %w", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(io.LimitReader(resp.Body, 1<<20))
if err != nil {
return nil, fmt.Errorf("read response: %w", err)
}
if resp.StatusCode != http.StatusOK {View on GitHub (pinned to 7944b8e522)
Solutions
- Print/inspect the full URL string passed to InitiateDeviceAuth and fix invalid characters or empty scheme
- Verify the endpoint configuration source (env var, config file) for typos
- If a proxy base URL is configurable, validate it parses with url.Parse before calling
- Retry is pointless here — correct the configuration and call again
Example fix
// before
u := os.Getenv("HYPER_API_URL")
auth, err := InitiateDeviceAuth(ctx, client, u)
// after
u := os.Getenv("HYPER_API_URL")
if _, err := url.Parse(u); err != nil || u == "" {
return fmt.Errorf("invalid HYPER_API_URL: %q", u)
}
auth, err := InitiateDeviceAuth(ctx, client, u) Defensive patterns
Strategy: validation
Validate before calling
func validateEndpoint(base string) error {
if base == "" { return fmt.Errorf("endpoint empty") }
u, err := url.Parse(base)
if err != nil { return err }
if u.Scheme != "https" || u.Host == "" { return fmt.Errorf("bad endpoint: %q", base) }
return nil
}
// call before InitiateDeviceAuth Try / catch
auth, err := InitiateDeviceAuth(ctx, client, endpoint)
if err != nil && strings.Contains(err.Error(), "create request") {
return fmt.Errorf("misconfigured Hyper endpoint %q: %w", endpoint, err)
} Prevention
- Validate the endpoint URL with url.Parse before constructing requests
- Reject URLs containing whitespace, newlines, or control characters
- Log the resolved full URL when configuration errors occur
When it happens
Trigger: http.NewRequestWithContext returns an error, practically always because the configured base URL plus path forms an invalid URL (unparsable scheme/host, control characters) or a bad context value.
Common situations: Misconfigured endpoint URL in settings/env (typo, empty, or containing whitespace/newline); an interceptor or test harness supplying a bogus URL; malformed context key affecting header interpolation.
Related errors
- ${ErrorDescription}
- device code request failed: %s - %s
- failed to create OAuth handler for mcp %q: %w
- oauth token source: %w
- failed to get MCP auth URL: status code %d
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/1df2fe55099c4edc.
Report an issue: GitHub.