{"record":{"id":"4d2118b10c26ca04","repo":"gastownhall/beads","slug":"create-request-w-4d2118","errorCode":null,"errorMessage":"create request: %w","messagePattern":"create request: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/notion/client.go","lineNumber":271,"sourceCode":"\t\thttpClient = &http.Client{Timeout: DefaultTimeout}\n\t}\n\n\tvar bodyReader io.Reader\n\tif requestBody != nil {\n\t\tpayload, err := json.Marshal(requestBody)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"marshal request body: %w\", err)\n\t\t}\n\t\tbodyReader = bytes.NewReader(payload)\n\t}\n\n\trequestURL := path\n\tif !strings.HasPrefix(requestURL, \"http://\") && !strings.HasPrefix(requestURL, \"https://\") {\n\t\trequestURL = strings.TrimSuffix(c.BaseURL, \"/\") + path\n\t}\n\treq, err := http.NewRequestWithContext(ctx, method, requestURL, bodyReader)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"create request: %w\", err)\n\t}\n\treq.Header.Set(\"Authorization\", \"Bearer \"+c.Token)\n\treq.Header.Set(\"Notion-Version\", c.NotionVersion)\n\treq.Header.Set(\"Accept\", \"application/json\")\n\tif requestBody != nil {\n\t\treq.Header.Set(\"Content-Type\", \"application/json\")\n\t}\n\n\tresp, err := httpClient.Do(req) //nolint:gosec // G704: URL is constructed from configured Notion API base, not user input\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"request failed: %w\", err)\n\t}\n\tdefer func() { _ = resp.Body.Close() }()\n\n\tbody, err := io.ReadAll(io.LimitReader(resp.Body, maxResponseBytes))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"read response: %w\", err)\n\t}","sourceCodeStart":253,"sourceCodeEnd":289,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/notion/client.go#L253-L289","documentation":"http.NewRequestWithContext failed while constructing the outgoing Notion HTTP request. With a fixed method and URL scheme this is rare, and almost always means the assembled requestURL is malformed (unparseable URL) or the context is already cancelled/invalid. The error is wrapped so the net/http cause is preserved.","triggerScenarios":"c.BaseURL misconfigured so the concatenated URL is invalid (e.g. BaseURL containing spaces or garbage); calling a wrapper with a path containing unescaped characters; passing an already-cancelled context is not it - that fails later - but an invalid URL/control characters in method or URL will trigger this.","commonSituations":"Config file with NOTION_BASE_URL pointing to a wrong, typo'd, or containing-invalid-characters value (spaces, newline); overriding BaseURL to a proxy URL with stray characters; tests constructing Client{BaseURL: \"://bad\"}.","solutions":["Inspect the wrapped error for 'parse ...' to see the malformed URL, then fix BaseURL (must be a valid absolute URL like https://api.notion.com/v1).","Trim whitespace/newlines from the configured base URL before constructing the client.","Leave BaseURL at its default unless you intentionally use a proxy/gateway.","Test URL assembly: u, err := url.Parse(strings.TrimSuffix(baseURL, \"/\") + path); validate err at startup."],"exampleFix":"// before\nclient := notion.NewClientWithBaseURL(\"https://api.notion.com/v1 \n\") // invalid URL\n\n// after\nbaseURL := strings.TrimSpace(cfg.NotionBaseURL)\nu, err := url.Parse(baseURL)\nif err != nil || u.Scheme == \"\" {\n    return fmt.Errorf(\"invalid notion base URL: %w\", err)\n}\nclient := notion.NewClientWithBaseURL(baseURL)","handlingStrategy":"validation","validationCode":"u, err := url.Parse(strings.TrimSuffix(baseURL, \"/\") + path)\nif err != nil {\n    return fmt.Errorf(\"invalid notion URL: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"create request\") {\n    log.Printf(\"check NOTION_BASE_URL / request path: %v\", err)\n}","preventionTips":["Trim whitespace/newlines from BaseURL at config load time.","Validate BaseURL with url.Parse at startup; require an https scheme.","Keep BaseURL at the library default unless a proxy is required."],"tags":["notion","http","url","request-construction"],"backgroundTag":"invalid-request-url","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}