{"record":{"id":"ba36c1347681588d","repo":"sipeed/picoclaw","slug":"empty-chat-id","errorCode":null,"errorMessage":"empty chat id","messagePattern":"empty chat id","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/channels/whatsapp_native/whatsapp_native.go","lineNumber":453,"sourceCode":"\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid chat id %q: %w\", msg.ChatID, err)\n\t}\n\n\twaMsg := &waE2E.Message{\n\t\tConversation: proto.String(msg.Content),\n\t}\n\n\tif _, err = client.SendMessage(ctx, to, waMsg); err != nil {\n\t\treturn nil, fmt.Errorf(\"whatsapp send: %w\", channels.ErrTemporary)\n\t}\n\treturn nil, nil\n}\n\n// parseJID converts a chat ID (phone number or JID string) to types.JID.\nfunc parseJID(s string) (types.JID, error) {\n\ts = strings.TrimSpace(s)\n\tif s == \"\" {\n\t\treturn types.JID{}, fmt.Errorf(\"empty chat id\")\n\t}\n\tif strings.Contains(s, \"@\") {\n\t\treturn types.ParseJID(s)\n\t}\n\treturn types.NewJID(s, types.DefaultUserServer), nil\n}\n","sourceCodeStart":435,"sourceCodeEnd":460,"githubUrl":"https://github.com/sipeed/picoclaw/blob/49183d7e8daed0dba89ddbb6fcb60089401d9680/pkg/channels/whatsapp_native/whatsapp_native.go#L435-L460","documentation":"Returned by parseJID in the native WhatsApp channel when the chat id is empty after strings.TrimSpace. It is a plain error (no sentinel), typically surfaced to callers wrapped as 'invalid chat id %q: empty chat id' by Send. It indicates an upstream data problem: an empty/whitespace recipient reached the channel.","triggerScenarios":"Send() called with msg.ChatID == \"\" or containing only spaces/tabs; upstream router forwarded a message whose destination was never populated.","commonSituations":"Automation/bridge code building outbound messages with an unset ChatID field; config templates with an empty recipient placeholder; trimming bugs that reduce ids to whitespace.","solutions":["Populate msg.ChatID with a phone number ('15551234567') or JID ('15551234567@s.whatsapp.net') before sending.","Add a non-empty check at the call site or in your message-building code.","Audit upstream routing for where the empty destination originated.","Treat as permanent - do not retry; drop or dead-letter such messages."],"exampleFix":"// before\nmsg := bus.OutboundMessage{ChatID: cfg.Recipient, Content: text} // cfg.Recipient == \"\"\n// after\nif strings.TrimSpace(cfg.Recipient) == \"\" {\n    return fmt.Errorf(\"recipient not configured\")\n}\nmsg := bus.OutboundMessage{ChatID: cfg.Recipient, Content: text}","handlingStrategy":"validation","validationCode":"if strings.TrimSpace(msg.ChatID) == \"\" {\n    return errors.New(\"refusing to send: empty chat id\")\n}","typeGuard":null,"tryCatchPattern":"if _, err := ch.Send(ctx, msg); err != nil {\n    if strings.Contains(err.Error(), \"empty chat id\") {\n        // permanent input bug: fix producer; do not retry\n    }\n}","preventionTips":["Require non-empty recipients at message-construction time.","Add integration tests asserting empty ChatID never reaches a channel.","Trim and validate ids once, at the edge of your pipeline."],"tags":["whatsapp","jid","validation","empty-input"],"backgroundTag":null,"analyzedSha":"49183d7e8daed0dba89ddbb6fcb60089401d9680","analyzedAt":"2026-08-15T21:55:41.315Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}