sipeed/picoclaw · error
WeCom QR scan succeeded but bot credentials are missing
Error message
WeCom QR scan succeeded but bot credentials are missing
What it means
The relay reported scan status 'success' but the botInfo payload inside it was incomplete: BotID or Secret was an empty string. The code refuses to return credentials that would later fail channel startup — a defensive check against a truncated/malformed success response.
Source
Thrown at cmd/picoclaw/internal/auth/wecom.go:300
timeoutCtx, cancel := context.WithTimeout(ctx, opts.PollTimeout)
defer cancel()
var scannedPrinted bool
for {
status, err := queryWeComQRCodeStatus(timeoutCtx, opts, scode)
if err != nil {
if errors.Is(err, context.DeadlineExceeded) || errors.Is(timeoutCtx.Err(), context.DeadlineExceeded) {
return wecomQRBotInfo{}, fmt.Errorf("WeCom QR scan timed out after %s", opts.PollTimeout)
}
return wecomQRBotInfo{}, err
}
switch strings.ToLower(status.Data.Status) {
case "success":
if status.Data.BotInfo.BotID == "" || status.Data.BotInfo.Secret == "" {
return wecomQRBotInfo{}, fmt.Errorf("WeCom QR scan succeeded but bot credentials are missing")
}
return wecomQRBotInfo{
BotID: status.Data.BotInfo.BotID,
Secret: status.Data.BotInfo.Secret,
}, nil
case "expired":
return wecomQRBotInfo{}, fmt.Errorf("WeCom QR code expired, please retry")
case "scaned", "scanned":
if !scannedPrinted {
fmt.Fprintln(opts.Writer, "QR code scanned. Confirm the login in WeCom.")
scannedPrinted = true
}
}
select {
case <-timeoutCtx.Done():
if errors.Is(timeoutCtx.Err(), context.DeadlineExceeded) {
return wecomQRBotInfo{}, fmt.Errorf("WeCom QR scan timed out after %s", opts.PollTimeout)View on GitHub (pinned to 49183d7e8d)
Solutions
- Retry the QR login — a fresh session usually gets a fully populated botInfo
- Update picoclaw to pick up any response-schema fixes
- If reproducible, capture the relay response (e.g. with a logging proxy) and report to maintainers
- Check the relay service status for provisioning incidents
Defensive patterns
Strategy: validation
Validate before calling
// Validate before trusting a success payload
if status.Data.BotInfo.BotID == "" || status.Data.BotInfo.Secret == "" {
// treat as incomplete: re-generate QR instead of propagating bad creds
} Type guard
func hasBotCredentials(info wecomQRBotInfo) bool {
return strings.TrimSpace(info.BotID) != "" && strings.TrimSpace(info.Secret) != ""
} Prevention
- Never persist or return bot credentials that fail the non-empty check
- Retry the full QR flow on hollow success responses — usually a relay race
When it happens
Trigger: Relay marks the scan successful before the bot is fully provisioned, returning empty bot fields; relay response schema change renames bot_id/secret so they decode as empty strings; relay bug during high load.
Common situations: Race on the relay side between confirmation and bot provisioning; API field rename between picoclaw and relay versions; partial outage producing hollow success responses.
Related errors
- failed to get WeCom QR code: response missing scode or auth_
- invalid WeCom QR generate URL: %w
- invalid WeCom QR query URL: %w
- invalid WeCom QR page URL: %w
- no models available
AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15).
Data as JSON: /api/errors/dc3fd06380766fd4.
Report an issue: GitHub.