{"record":{"id":"13a59722ab392a68","repo":"router-for-me/CLIProxyAPI","slug":"codex-live-multipart-boundary-is-missing","errorCode":null,"errorMessage":"Codex live multipart boundary is missing","messagePattern":"Codex live multipart boundary is missing","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"internal/client/codex/live/live.go","lineNumber":622,"sourceCode":"\t\tif errMarshal != nil {\n\t\t\treturn nil, \"\", fmt.Errorf(\"failed to encode Realtime model: %w\", errMarshal)\n\t\t}\n\t\tpayload[\"model\"] = encodedModel\n\t\tchanged = true\n\t}\n\tif !changed {\n\t\treturn body, upstreamModel, nil\n\t}\n\tencoded, errMarshal := json.Marshal(payload)\n\tif errMarshal != nil {\n\t\treturn nil, \"\", fmt.Errorf(\"failed to encode Realtime call request: %w\", errMarshal)\n\t}\n\treturn encoded, upstreamModel, nil\n}\n\nfunc multipartCallRequest(body []byte, boundary string) ([]byte, string, string, error) {\n\tif boundary == \"\" {\n\t\treturn nil, \"\", \"\", errors.New(\"Codex live multipart boundary is missing\")\n\t}\n\n\treader := multipart.NewReader(bytes.NewReader(body), boundary)\n\tvar sdp *string\n\tvar session json.RawMessage\n\tmodel := \"\"\n\tfor {\n\t\tpart, errPart := reader.NextPart()\n\t\tif errors.Is(errPart, io.EOF) {\n\t\t\tbreak\n\t\t}\n\t\tif errPart != nil {\n\t\t\treturn nil, \"\", \"\", fmt.Errorf(\"failed to parse Codex live multipart body: %w\", errPart)\n\t\t}\n\t\tpartBody, errRead := io.ReadAll(part)\n\t\terrClose := part.Close()\n\t\tif errRead != nil {\n\t\t\treturn nil, \"\", \"\", fmt.Errorf(\"failed to read Codex live multipart field: %w\", errRead)","sourceCodeStart":604,"sourceCodeEnd":640,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/client/codex/live/live.go#L604-L640","documentation":"http.NewRequestWithContext failed while turning the plugin-supplied pluginapi.HTTPRequest into a real *http.Request. The method defaults to GET when empty, so failure almost always means an invalid URL (unsupported scheme, control characters, unparsable target) or an invalid method token; the config is still returned alongside the error.","triggerScenarios":"Plugin passes req.URL that is empty, lacks a scheme (\"api.example.com/v1\" instead of \"https://...\"), contains spaces/control chars, or uses a scheme Go rejects (e.g. \"ftp://\"-style unsupported by the transport expectations); or req.Method is an invalid HTTP token like \"get x\".","commonSituations":"Building URLs from unescaped user input; forgetting the https:// prefix; trailing whitespace in URL config; plugin porting from a client library that tolerates relative URLs.","solutions":["Normalize and validate the URL in the plugin before calling: url.Parse, require a non-empty scheme and host.","Prepend \"https://\" when the scheme is missing.","Use url.Values / url.PathEscape for query and path components."],"exampleFix":"// before\nreq := pluginapi.HTTPRequest{Method: \"GET\", URL: rawTarget} // rawTarget = \"api.example.com/v1/models\"\n\n// after\nif !strings.Contains(rawTarget, \"://\") {\n    rawTarget = \"https://\" + rawTarget\n}\nu, err := url.Parse(rawTarget)\nif err != nil || u.Scheme == \"\" || u.Host == \"\" {\n    return fmt.Errorf(\"invalid target URL %q\", rawTarget)\n}\nreq := pluginapi.HTTPRequest{Method: \"GET\", URL: u.String()}","handlingStrategy":"validation","validationCode":"func validHTTPURL(target string) bool {\n    if !strings.Contains(target, \"://\") {\n        target = \"https://\" + target\n    }\n    u, err := url.Parse(target)\n    return err == nil && u.Scheme != \"\" && u.Host != \"\"\n}\n\nif !validHTTPURL(req.URL) {\n    return fmt.Errorf(\"invalid target URL %q\", req.URL)\n}","typeGuard":null,"tryCatchPattern":"resp, err := http.Do(ctx, req)\nif err != nil {\n    var urlErr *url.Error\n    if errors.As(err, &urlErr) && strings.Contains(urlErr.Err.Error(), \"invalid\") {\n        return fmt.Errorf(\"malformed request (URL/method): %w\", err) // fix input, never retry\n    }\n    return err\n}","preventionTips":["Escape all URL components with net/url helpers.","Always include the scheme.","Default the method explicitly rather than relying on empty-string coercion downstream."],"tags":["pluginhost","http","url","validation"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}