{"record":{"id":"2ddf1efcc5f441f6","repo":"charmbracelet/crush","slug":"could-not-create-request-w","errorCode":null,"errorMessage":"could not create request: %w","messagePattern":"could not create request: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/agent/hyper/provider.go","lineNumber":87,"sourceCode":"//\n// It returns nil when the team has hypercredit display disabled, in which\n// case Hyper reports the balance in dollars instead and there is no\n// hypercredit figure to show.\nfunc FetchCredits(ctx context.Context, apiKey string) (*int, error) {\n\tif hasBalance.Load() {\n\t\thasBalance.Store(false)\n\t\tbalance := int(lastKnownBalance.Load())\n\t\treturn &balance, nil\n\t}\n\n\treq, err := http.NewRequestWithContext(\n\t\tctx,\n\t\thttp.MethodGet,\n\t\tBaseURL()+\"/v1/credits\",\n\t\tnil,\n\t)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"could not create request: %w\", err)\n\t}\n\treq.Header.Set(\"Authorization\", \"Bearer \"+apiKey)\n\n\tclient := &http.Client{Timeout: 10 * time.Second}\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to make request: %w\", err)\n\t}\n\tdefer resp.Body.Close() //nolint:errcheck\n\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn nil, fmt.Errorf(\"unexpected status code: %d\", resp.StatusCode)\n\t}\n\n\t// Teams with hypercredit display disabled get a balance_usd field\n\t// instead of balance, and no balance is shown for them at all.\n\tvar result struct {\n\t\tBalance *int `json:\"balance\"`","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/agent/hyper/provider.go#L69-L105","documentation":"FetchCredits wraps any error returned by http.NewRequestWithContext when constructing the GET request to <BaseURL>/v1/credits. In practice this only fails if the composed URL is malformed (unparseable) or the context is invalid, since the method and nil body are constants. It indicates the request never left the client.","triggerScenarios":"HYPER_URL is set to a value that makes BaseURL()+\"/v1/credits\" an unparseable URL (e.g. contains control characters, spaces, or an invalid scheme like \"foo bar://x\"); or the passed context is already canceled/invalid in a way NewRequestWithContext rejects.","commonSituations":"Developers misconfigure the HYPER_URL environment variable (trailing garbage, quotes included, whitespace) when pointing Crush Hyper at a self-hosted proxy; the URL concatenation then produces an invalid url.URL.","solutions":["Print and inspect the env value with `echo \"${HYPER_URL}\" | cat -A` and fix HYPER_URL to a clean absolute URL like https://my-proxy.example.com (no spaces/quotes).","Validate the URL before calling FetchCredits: u, err := url.Parse(hyper.BaseURL()+\"/v1/credits\"); require err == nil and u.Scheme != \"\" && u.Host != \"\".","Ensure the context passed in is live (not already canceled) and carries no invalid values.","Unset HYPER_URL to fall back to the default https://hyper.charm.land and retry."],"exampleFix":"// before\nos.Setenv(\"HYPER_URL\", \"https://my proxy.example.com\") // invalid: space in host\nbalance, err := hyper.FetchCredits(ctx, apiKey)\n// after\nbase := strings.TrimRight(strings.TrimSpace(os.Getenv(\"HYPER_URL\")), \"/\")\nif u, err := url.Parse(base + \"/v1/credits\"); err != nil || u.Host == \"\" {\n    base = \"https://hyper.charm.land\" // fall back to default\n}\n_ = base // use validated base URL / corrected HYPER_URL before calling FetchCredits","handlingStrategy":"validation","validationCode":"u, err := url.Parse(hyper.BaseURL() + \"/v1/credits\")\nif err != nil || u.Scheme == \"\" || u.Host == \"\" {\n    return fmt.Errorf(\"invalid HYPER_URL %q: %w\", os.Getenv(\"HYPER_URL\"), err)\n}","typeGuard":"func validURL(raw string) bool {\n    u, err := url.Parse(raw)\n    return err == nil && (u.Scheme == \"http\" || u.Scheme == \"https\") && u.Host != \"\"\n}","tryCatchPattern":"balance, err := hyper.FetchCredits(ctx, apiKey)\nif err != nil {\n    if strings.Contains(err.Error(), \"could not create request\") {\n        log.Fatalf(\"check HYPER_URL: %v\", err)\n    }\n    return err\n}","preventionTips":["Trim and validate HYPER_URL at startup, rejecting values that fail url.Parse.","Never paste URLs with surrounding quotes or whitespace into env files.","Add a startup config check that verifies BaseURL()+' /v1/credits' parses before first use."],"tags":["http","url-parsing","configuration","go"],"backgroundTag":"malformed-url","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}