{"record":{"id":"a561217f1254d1fe","repo":"chenhg5/cc-connect","slug":"create-request-w-a56121","errorCode":null,"errorMessage":"create request: %w","messagePattern":"create request: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"info","filePath":"platform/dingtalk/card.go","lineNumber":121,"sourceCode":"\t\tpayload[\"imRobotOpenDeliverModel\"] = map[string]any{\n\t\t\t\"spaceType\": \"IM_ROBOT\",\n\t\t\t\"robotCode\": p.robotCode,\n\t\t}\n\t}\n\n\tbodyBytes, err := json.Marshal(payload)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"marshal payload: %w\", err)\n\t}\n\n\treqCtx, cancel := context.WithTimeout(ctx, 30*time.Second)\n\tdefer cancel()\n\n\treq, err := http.NewRequestWithContext(reqCtx, http.MethodPost,\n\t\t\"https://api.dingtalk.com/v1.0/card/instances/createAndDeliver\",\n\t\tbytes.NewReader(bodyBytes))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"create request: %w\", err)\n\t}\n\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\treq.Header.Set(\"x-acs-dingtalk-access-token\", token)\n\n\tslog.Debug(\"dingtalk: creating AI card\", \"outTrackId\", outTrackId, \"isGroup\", isGroup)\n\n\tresp, err := p.httpClient.Do(req)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"do request: %w\", err)\n\t}\n\tdefer resp.Body.Close()\n\n\trespBody, _ := io.ReadAll(resp.Body)\n\n\tslog.Debug(\"dingtalk: createAndDeliver response\",\n\t\t\"status\", resp.StatusCode,\n\t\t\"body\", string(respBody))","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/dingtalk/card.go#L103-L139","documentation":"This error wraps a failure from http.NewRequestWithContext when building the POST to https://api.dingtalk.com/v1.0/card/instances/createAndDeliver (platform/dingtalk/card.go:121, createAICard). NewRequest only errors on an invalid method, malformed URL, or a nil/invalid body reader, so with the hardcoded POST and constant URL this is effectively unreachable and signals a programming/environmental invariant break.","triggerScenarios":"http.NewRequestWithContext rejects the hardcoded method POST, the constant URL https://api.dingtalk.com/v1.0/card/instances/createAndDeliver, or the bytes.NewReader(bodyBytes) body; bodyBytes is always non-nil so this practically cannot fire in stock code.","commonSituations":"Source modifications that parameterize the URL with an invalid value (spaces, control characters, bad scheme) or change the HTTP method to an invalid token; corporate proxies never cause this (they fail later at do request).","solutions":["Verify the URL constant is unmodified and contains no spaces or invalid characters (url.Parse the value manually to see the exact error)","If the URL is now configurable, validate it with url.Parse and http.CanonicalHeaderKey-style checks before constructing the request","Confirm the HTTP method string is exactly \"POST\" with no whitespace","If untouched stock code, report as a bug including the wrapped error"],"exampleFix":"// before (interpolated, unvalidated URL)\nurl := cfg.CardURL // may be empty or malformed\n// after\nu, err := url.Parse(cfg.CardURL)\nif err != nil || u.Scheme == \"\" || u.Host == \"\" { return nil, fmt.Errorf(\"invalid card url: %w\", err) }","handlingStrategy":"validation","validationCode":"u, err := url.Parse(\"https://api.dingtalk.com/v1.0/card/instances/createAndDeliver\")\nif err != nil || u.Scheme != \"https\" || u.Host == \"\" {\n\t// fail fast before building request\n}","typeGuard":null,"tryCatchPattern":"card, err := p.CreateStreamingCard(ctx, rc)\nif err != nil && strings.Contains(err.Error(), \"create request:\") {\n\tlog.Printf(\"request construction invariant broken: %v\", err)\n}","preventionTips":["Keep API URLs as compile-time constants","Validate any externalized URL with url.Parse before use","Never build method strings from user/config input"],"tags":["go","http","dingtalk","request-construction"],"backgroundTag":"invalid-url","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}