{"record":{"id":"75c2e0c6b8dd8ac8","repo":"chenhg5/cc-connect","slug":"googlechat-build-request-w-75c2e0","errorCode":null,"errorMessage":"googlechat: build request: %w","messagePattern":"googlechat: build request: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/googlechat/streaming.go","lineNumber":39,"sourceCode":"// SendPreviewStart posts the initial streaming-preview message (threaded like a\n// normal reply) and returns a handle for subsequent edits. Implements\n// core.PreviewStarter; together with UpdateMessage it lights up the engine's\n// real-time streaming preview for Google Chat.\nfunc (p *Platform) SendPreviewStart(ctx context.Context, rctx any, content string) (any, error) {\n\trc, ok := rctx.(replyContext)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"googlechat: invalid reply context type %T\", rctx)\n\t}\n\tif rc.space == \"\" {\n\t\treturn nil, fmt.Errorf(\"googlechat: missing space in reply context\")\n\t}\n\turl, body, err := buildSendRequest(rc, content)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treq, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(body))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"googlechat: build request: %w\", err)\n\t}\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\tresp, err := p.doRequest(req)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"googlechat: send preview: %w\", err)\n\t}\n\tdefer func() {\n\t\tif err := resp.Body.Close(); err != nil {\n\t\t\tslog.Warn(\"googlechat: close preview response body\", \"error\", err)\n\t\t}\n\t}()\n\tvar msg struct {\n\t\tName string `json:\"name\"`\n\t}\n\tif err := json.NewDecoder(resp.Body).Decode(&msg); err != nil {\n\t\treturn nil, fmt.Errorf(\"googlechat: parse create response: %w\", err)\n\t}\n\t// drain any bytes json.Decoder left unread so the connection is reusable","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/googlechat/streaming.go#L21-L57","documentation":"Wraps a failure from http.NewRequestWithContext when constructing the preview message POST in SendPreviewStart. Since the method is a constant, the only realistic cause is an invalid URL coming out of buildSendRequest.","triggerScenarios":"buildSendRequest returns a URL that fails URL parsing — usually an empty or malformed configured API base URL, or unescaped characters in the space name interpolated into the URL.","commonSituations":"Bad base-URL override in config; spaces/thread keys with special characters; regressions after library upgrades.","solutions":["Log and validate the URL from buildSendRequest with url.Parse","Confirm the Chat API base URL is the standard https://chat.googleapis.com/v1/...","URL-escape space and thread identifiers before interpolation"],"exampleFix":"// before\nurl := baseURL + \"/spaces/\" + rc.space + \"/messages\"\n// after\nurl := baseURL + \"/spaces/\" + url.PathEscape(rc.space) + \"/messages\"","handlingStrategy":"validation","validationCode":"u := buildPreviewURL(rc)\nif _, err := url.Parse(u); err != nil || !strings.HasPrefix(u, \"https://\") { return fmt.Errorf(\"invalid preview URL: %w\", err) }","typeGuard":null,"tryCatchPattern":"if _, err := p.SendPreviewStart(ctx, rc, content); err != nil {\n    if strings.Contains(err.Error(), \"build request\") { slog.Error(\"googlechat preview URL malformed\", \"error\", err) }\n    return err\n}","preventionTips":["Validate the configured Chat API base URL at startup","Escape space/thread identifiers in URLs","Add a regression test for URL building"],"tags":["googlechat","http","url","streaming"],"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"}