Skip to content

Key bad-credentials notice cooldowns by error code#33

Merged
Just-Insane merged 1 commit into
mainfrom
fix/bad-credentials-cooldown-by-errorcode
Jul 2, 2026
Merged

Key bad-credentials notice cooldowns by error code#33
Just-Insane merged 1 commit into
mainfrom
fix/bad-credentials-cooldown-by-errorcode

Conversation

@Just-Insane

Copy link
Copy Markdown

Summary

Follow-up to #32, which merged before this was caught by a delayed Codex review pass on that PR (linking here since #32's own thread is now closed): comment.

That PR's resend-cooldown fix (itself a fix for a different bug: sentBadCredentialsNotice never resetting since handlePossible40002 doesn't log the user out) didn't distinguish which error code was last notified. Concretely: if a 40002 notice sends successfully, a real 4004 full logout arriving within the following hour would get suppressed by the 40002's resend cooldown — leaving the user staring at "you do not need to log in" advice even though their token was actually just cleared and they do need to log in now.

badCredentialsNoticeAttemptDecision now takes both the incoming and last-notified error codes; the cooldowns only apply when they match. A different code always gets through immediately, since it may carry materially different (even opposite) recovery instructions.

Test plan

  • go build ./... / go vet ./... / gofmt — clean
  • go test ./... -race — clean
  • New test cases covering both cooldowns bypassed when the error code differs from the last notified one.

🤖 Generated with Claude Code

Follow-up to the resend-cooldown fix (which addressed a different
bug: sentBadCredentialsNotice never resetting since
handlePossible40002 doesn't log the user out). That fix's cooldown
didn't distinguish which kind of bad-credentials event was last
notified: if a 40002 notice sent successfully, a real 4004 full
logout arriving within the following hour would be suppressed by the
40002's resend cooldown -- leaving the user with stale "you do not
need to log in" advice even after their token was actually cleared
and login is now required.

badCredentialsNoticeAttemptDecision now takes both the incoming and
last-notified error codes and only applies either cooldown when they
match; a different code always gets through immediately, since it may
carry materially different (even opposite) recovery instructions.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 2, 2026 17:58
@Just-Insane Just-Insane merged commit 7c7d556 into main Jul 2, 2026
5 of 6 checks passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refines the bad-credentials notice cooldown logic so the cooldown only suppresses repeat notices for the same underlying Discord error code, preventing stale/incorrect recovery instructions from being shown when a different invalidation scenario occurs shortly after.

Changes:

  • Track lastBadCredentialsErrorCode on User and reset it on successful Login.
  • Update badCredentialsNoticeAttemptDecision to bypass cooldowns when the incoming error code differs from the last-notified code.
  • Extend unit tests to cover cooldown bypass when error codes differ.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
user.go Adds per-last-error-code tracking and updates cooldown gating to only apply when error codes match.
user_notice_test.go Adds test cases validating that differing error codes bypass active cooldowns.
Comments suppressed due to low confidence (1)

user.go:2378

  • time.Now() is called twice while holding bridgeStateLock (once for the cooldown decision and again when recording lastBadCredentialsNoticeAttempt). Using a single timestamp avoids minor inconsistencies and makes the state update easier to reason about (especially around cooldown boundaries).
	attempt, skipReason := badCredentialsNoticeAttemptDecision(user.sentBadCredentialsNotice, errorCode, user.lastBadCredentialsErrorCode, user.lastBadCredentialsNoticeAttempt, time.Now())
	if !attempt {
		user.bridgeStateLock.Unlock()
		log.Debug().Bool("notice_sent", false).Msg("Bad credentials event (" + skipReason + ")")
		return

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants