{"record":{"id":"5b929a04c4beedf0","repo":"chenhg5/cc-connect","slug":"webex-postmessage-status-d","errorCode":null,"errorMessage":"webex: postMessage status %d","messagePattern":"webex: postMessage status (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/webex/client.go","lineNumber":217,"sourceCode":"\t\t\tf.FileName = params[\"filename\"]\n\t\t}\n\t}\n\treturn f, nil\n}\n\nfunc (c *httpClient) PostMessage(ctx context.Context, roomID, parentID, markdown string) error {\n\tbody := map[string]string{\"roomId\": roomID, \"markdown\": markdown}\n\tif parentID != \"\" {\n\t\tbody[\"parentId\"] = parentID\n\t}\n\tbuf, _ := json.Marshal(body)\n\tresp, err := c.doWithRetry(ctx, http.MethodPost, c.base()+\"/messages\", buf, \"application/json\", \"webex: postMessage\")\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer func() { _ = resp.Body.Close() }()\n\tif resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated {\n\t\treturn fmt.Errorf(\"webex: postMessage status %d\", resp.StatusCode)\n\t}\n\treturn nil\n}\n\nfunc (c *httpClient) PostFile(ctx context.Context, roomID string, f *downloadedFile) error {\n\tvar buf bytes.Buffer\n\tw := multipart.NewWriter(&buf)\n\t_ = w.WriteField(\"roomId\", roomID)\n\tname := f.FileName\n\tif name == \"\" {\n\t\tname = \"attachment\"\n\t}\n\tpart, err := w.CreateFormFile(\"files\", name)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif _, err := part.Write(f.Data); err != nil {\n\t\treturn err","sourceCodeStart":199,"sourceCodeEnd":235,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/webex/client.go#L199-L235","documentation":"The POST to /messages with roomId/markdown(/parentId) returned a status outside the accepted success set (200, 201). It means Webex refused to deliver the reply — typical causes are an invalid or archived roomId, an expired token (401), or rate limiting that survived doWithRetry's backoff.","triggerScenarios":"POST /messages returns 400 (bad roomID/personID/email format), 401 (bad token), 404 (room deleted or bot not in room), 429 (rate limit), or 5xx.","commonSituations":"Bot removed from the room after being mentioned; invalid personEmail in targeted messages; hitting Webex API rate limits during bursts; expired bot token.","solutions":["Inspect the status code: 404 → verify the bot is still a member of the room; 400 → validate roomID/personEmail format","Handle 429 by backing off and retrying (Webex rate limits per token)","Check that the room ID is the Webex room UUID (prefix Y2lzY29zcGFyazovL3...)","Refresh the bot token if 401 occurs repeatedly"],"exampleFix":"// before\nclient.PostMessage(ctx, roomIDFromUser, text) // roomID typed by user\n// after\nif !strings.HasPrefix(roomIDFromUser, \"Y2lzY29zcGFyazovL3\") {\n    return fmt.Errorf(\"invalid room id\")\n}\nclient.PostMessage(ctx, roomIDFromUser, text)","handlingStrategy":"retry","validationCode":"if roomID == \"\" || !strings.HasPrefix(roomID, \"Y2lzY29zcGFyazovL3\") { return errors.New(\"invalid room id\") }","typeGuard":null,"tryCatchPattern":"err := client.PostMessage(ctx, roomID, text)\nif err != nil {\n    if strings.Contains(err.Error(), \"status 429\") { backoffAndRetry() }\n    if strings.Contains(err.Error(), \"status 404\") { alertBotRemovedFromRoom() }\n    return err\n}","preventionTips":["Verify room IDs are Webex UUIDs before sending","Implement backoff for 429s on bursty traffic","Monitor bot membership in rooms","Rotate tokens before expiry"],"tags":["webex","http","api","message-send"],"backgroundTag":"http-error-response","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"}