Authentication Issues
“Invalid OAuth token” or 401 Unauthorized
Symptoms: API calls return 401 errors or “Invalid OAuth token” messages.
Solutions:
- Validate your token
validation, err := authClient.ValidateToken(ctx, token.AccessToken) if err != nil { // Token is invalid - refresh or re-authenticate } - Check token expiry - Access tokens expire after ~4 hours. Use refresh tokens:
newToken, err := authClient.RefreshToken(ctx, token.RefreshToken) - Verify token type - Some endpoints need user tokens, others need app tokens:
- User token:
GetUserswithIDsof other users - App token: Most read-only public data endpoints
- User token:
- Enable auto-refresh
cancel := authClient.AutoRefresh(ctx) defer cancel()
“Missing required scope”
Symptoms: API returns 403 with scope-related error message.
Solutions:
- Check the Twitch API docs for required scopes
- Re-authenticate with the needed scopes:
authClient := helix.NewAuthClient(helix.AuthConfig{ Scopes: []string{"channel:read:subscriptions", "channel:manage:broadcast"}, // ... }) - Validate your token to see current scopes:
validation, _ := authClient.ValidateToken(ctx, token) fmt.Println("Scopes:", validation.Scopes)
“Client ID and token mismatch”
Symptoms: 401 error mentioning client ID mismatch.
Solution: The token was created with a different Client ID. Either:
- Use the correct Client ID that matches the token
- Generate a new token with your Client ID
Note: When using WithToken for per-request token overrides, all tokens must belong to the same Client ID as the client. Twitch requires the Client-Id header and Authorization token to match.
EventSub Issues
Subscriptions stuck in “webhook_callback_verification_pending”
Symptoms: Webhook subscriptions never become enabled.
Solutions:
- Verify your endpoint is reachable - Twitch sends a challenge request that must be answered
- Check your callback URL - Must be HTTPS with valid certificate
- Return the challenge correctly:
handler := helix.NewEventSubWebhookHandler(secret, helix.WithEventSubChallengeHandler(func(challenge string) { // Handler returns challenge automatically }), ) - Check firewall/proxy settings - Ensure Twitch can reach your server
Not receiving WebSocket events
Symptoms: WebSocket connected but no events arrive.
Solutions:
- Verify subscription is active:
subs, _ := client.GetEventSubSubscriptions(ctx, nil) for _, sub := range subs.Data { fmt.Printf("%s: %s\n", sub.Type, sub.Status) } -
Check you’re subscribed to the right events - Use
SubscribeTo*methods after connecting - Trigger test events - Use the Twitch CLI to send test events:
twitch event trigger channel.follow -F wss://localhost:8080/eventsub - Verify your session ID - Subscriptions must use the session ID from the welcome message
“subscription limit reached”
Symptoms: Cannot create more EventSub subscriptions.
Solutions:
- WebSocket limit: 300 subscriptions per connection. Use multiple connections or webhooks.
- Total limit: 10,000 subscriptions total. Delete unused subscriptions:
client.DeleteEventSubSubscription(ctx, subscriptionID) - List and clean up:
subs, _ := client.GetEventSubSubscriptions(ctx, nil) for _, sub := range subs.Data { if sub.Status != "enabled" { client.DeleteEventSubSubscription(ctx, sub.ID) } }
IRC/Chat Issues
“Login authentication failed”
Symptoms: IRC connection fails with NOTICE about authentication.
Solutions:
- Check token format - Must include
oauth:prefix:helix.WithIRCToken("oauth:your-token-here") -
Verify token scopes - Need
chat:readto read,chat:editto send - Check username matches token - The nick must match the token owner:
helix.WithIRCNick("your_username")
Messages not sending
Symptoms: Say() returns no error but messages don’t appear.
Solutions:
- Join the channel first:
irc.Join("channelname") time.Sleep(time.Second) // Wait for join confirmation irc.Say("channelname", "Hello!") -
Check rate limits - 20 messages per 30 seconds for regular users
-
Verify you’re not banned/timed out in that channel
- Check for shadowban - Your messages might be hidden from others
Not receiving messages
Symptoms: Connected and joined but no messages received.
Solutions:
- Verify message handler is set:
helix.WithIRCMessageHandler(func(msg *helix.IRCMessage) { fmt.Printf("Received: %+v\n", msg) }) - Request capabilities - Kappopher requests these automatically, but verify:
twitch.tv/membership- JOIN/PART messagestwitch.tv/tags- User badges, emotestwitch.tv/commands- USERNOTICE, etc.
- Check the channel has activity - Try a popular channel to verify connection
API Issues
Empty response data
Symptoms: API returns successfully but Data is empty.
Solutions:
-
Resource doesn’t exist - User deleted, stream offline, etc.
- Check parameters:
// Wrong: searching by ID when you have login client.GetUsers(ctx, &helix.GetUsersParams{IDs: []string{"shroud"}}) // Correct: use the right parameter client.GetUsers(ctx, &helix.GetUsersParams{Logins: []string{"shroud"}}) - Paginate if needed - First page might be empty, check cursor:
if resp.Pagination != nil && resp.Pagination.Cursor != "" { // More data available }
“too many requests” / 429 errors
Symptoms: API returns 429 Too Many Requests.
Solutions:
- Check rate limit info:
remaining, reset := client.GetRateLimitInfo() if remaining == 0 { time.Sleep(time.Until(reset)) } - Use caching to reduce API calls:
client := helix.NewClient(clientID, authClient, helix.WithCache(helix.CacheConfig{ DefaultTTL: 5 * time.Minute, }), ) - Batch requests where possible:
// Instead of 100 individual calls client.GetUsers(ctx, &helix.GetUsersParams{ IDs: userIDs[:100], // Up to 100 at once })
Request timeout
Symptoms: Context deadline exceeded.
Solutions:
- Increase timeout:
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() -
Check network connectivity to Twitch servers
- Use a custom HTTP client with longer timeouts:
httpClient := &http.Client{Timeout: 60 * time.Second} client := helix.NewClient(clientID, authClient, helix.WithHTTPClient(httpClient), )
Connection Issues
WebSocket keeps disconnecting
Symptoms: Frequent disconnections from EventSub or IRC.
Solutions:
- Enable auto-reconnect:
helix.WithEventSubAutoReconnect(true) // or for IRC helix.WithIRCAutoReconnect(true) - Handle reconnection:
helix.WithEventSubReconnectHandler(func(oldID, newID string) { log.Println("Reconnected") }) - Check for network issues - Unstable connections, proxies, firewalls
“connection refused”
Symptoms: Cannot connect to Twitch servers.
Solutions:
- Check firewall - Allow outbound connections to:
api.twitch.tv(HTTPS/443)id.twitch.tv(HTTPS/443)eventsub.wss.twitch.tv(WSS/443)irc-ws.chat.twitch.tv(WSS/443)
-
Check proxy settings - Configure HTTP client if needed
- Verify DNS resolution - Try
ping api.twitch.tv
Still Having Issues?
- Enable debug logging to see raw requests/responses
- Check Twitch Status for outages
- Search existing issues
- Open a new issue with:
- Go version
- Kappopher version
- Minimal reproducible example
- Error messages/logs