Skip to content

fix: retry fallback for rejected replies by LINE#210

Merged
highesttt merged 1 commit into
mainfrom
highest/plat-37877
Jul 9, 2026
Merged

fix: retry fallback for rejected replies by LINE#210
highesttt merged 1 commit into
mainfrom
highest/plat-37877

Conversation

@highesttt

Copy link
Copy Markdown
Collaborator

No description provided.

@linear-code

linear-code Bot commented Jul 9, 2026

Copy link
Copy Markdown

PLAT-37877

@indent-zero

indent-zero Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor
PR Summary

Adds a targeted retry when LINE rejects a reply because it can't resolve the reply target, so the message still lands as a plain (non-reply) message instead of hard-failing. Introduces a shared line.IsTalkExceptionNotFound helper (with an explicit docstring warning that callers must supply method context) and broadens hasResponseErrorCode to accept a spaced "code": 10051 form.

  • pkg/connector/send_message.go: new post-send branch in HandleMatrixMessage that, when the outbound line.Message carries a reply relation and sendMessage fails with TalkException code 5 "not found", clears the reply fields (outer struct + defensive message_relation_* metadata keys), logs a WARN, generates a fresh reqSeq, and resends once. Adds helper functions shouldRetrySendWithoutReplyRelation and clearReplyRelation.
  • pkg/line/errors.go: adds IsTalkExceptionNotFound matching the compact and partially-spaced RESPONSE_ERROR / TalkException code 5 "not found" JSON shape; extends hasResponseErrorCode to also match "code": 10051.
  • Unit tests added for both helpers in pkg/connector/send_message_test.go and pkg/line/errors_test.go (positive case, wrong reason, wrong code, nil, and reply-relation gating).

Issues

2 potential issues found:

  • Retry may fire on unrelated TalkException code 5 errors (latent, triggered if sendMessage ever surfaces "not found" for a non-reply reason such as missing recipient/chat): shouldRetrySendWithoutReplyRelation only checks that msg.RelatedMessageID != "" and the error matches the generic not-found pattern, matching the docstring warning on IsTalkExceptionNotFound that callers must add method context. The doomed second send is user-invisible today, but the "could not find reply target" log will be misleading and, if the retry ever coincidentally succeeds, a reply would silently be downgraded to a non-reply. → Autofix
  • IsGroupKeyNotFound still hard-codes "code":10051 instead of routing through the updated hasResponseErrorCode helper, so the newly-accepted "code": 10051 (spaced) variant is only honored by the new IsTalkExceptionNotFound. No impact today because LINE returns compact JSON, but if the response ever gets pretty-printed the auto-register-group-key retry will silently regress while the new reply retry keeps working. → Autofix

CI Checks

Waiting for CI checks...


⚡ Autofix All Issues

@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2e0d7172-8827-4bf3-b012-82032812babc

📥 Commits

Reviewing files that changed from the base of the PR and between 2772f67 and e15af1c.

📒 Files selected for processing (4)
  • pkg/connector/send_message.go
  • pkg/connector/send_message_test.go
  • pkg/line/errors.go
  • pkg/line/errors_test.go

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.


📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes

    • Messages that fail because the original reply target can’t be found will now automatically resend without reply context, improving delivery success.
    • Error detection was broadened to recognize more variations of the same LINE “not found” response, making retries more reliable.
  • Tests

    • Added coverage for the new retry behavior and reply-context cleanup logic.

Walkthrough

Adds LINE TalkException "not found" error detection (IsTalkExceptionNotFound) and expands hasResponseErrorCode matching. HandleMatrixMessage retries message sends without reply relation when this error occurs, using new helpers shouldRetrySendWithoutReplyRelation and clearReplyRelation. Tests cover both new behaviors.

Changes

Retry without reply relation

Layer / File(s) Summary
TalkException not-found error detection
pkg/line/errors.go, pkg/line/errors_test.go
Adds exported IsTalkExceptionNotFound to detect LINE TalkException code 5 "not found" errors across JSON formatting variants, expands hasResponseErrorCode to match "code": 10051 with a space, and adds tests covering positive/negative/nil cases.
Retry send without reply relation
pkg/connector/send_message.go, pkg/connector/send_message_test.go
HandleMatrixMessage retries sending without a reply relation on "not found" failures via new shouldRetrySendWithoutReplyRelation and clearReplyRelation helpers, clearing relation fields/metadata and resending; tests verify retry conditions and relation-clearing behavior.

Estimated code review effort: 2 (Simple) | ~12 minutes

Sequence Diagram(s)

sequenceDiagram
  participant HandleMatrixMessage
  participant LINEAPI
  participant shouldRetrySendWithoutReplyRelation
  participant clearReplyRelation

  HandleMatrixMessage->>LINEAPI: Send message with RelatedMessageID
  LINEAPI-->>HandleMatrixMessage: Error (reply target not found)
  HandleMatrixMessage->>shouldRetrySendWithoutReplyRelation: Check RelatedMessageID and error
  shouldRetrySendWithoutReplyRelation-->>HandleMatrixMessage: true
  HandleMatrixMessage->>clearReplyRelation: Clear relation fields and metadata
  clearReplyRelation-->>HandleMatrixMessage: Message without relation
  HandleMatrixMessage->>LINEAPI: Resend message without RelatedMessageID
  LINEAPI-->>HandleMatrixMessage: Success
Loading
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch highest/plat-37877

Comment @coderabbitai help to get the list of available commands.

}

func shouldRetrySendWithoutReplyRelation(msg *line.Message, err error) bool {
return msg != nil && msg.RelatedMessageID != "" && line.IsTalkExceptionNotFound(err)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Broad match on TalkException code 5: IsTalkExceptionNotFound matches any code:5 reason:"not found" TalkException — the helper's own docstring in pkg/line/errors.go:148-150 warns that callers must interpret method context. Here the only additional guard is msg.RelatedMessageID != "", so if LINE's sendMessage ever surfaces a non-reply "not found" (e.g. recipient/chat missing) on a message that also carried a reply relation, we'd strip the reply and re-send once. Today that just costs one extra doomed request plus a misleading could not find reply target log; if the second attempt were ever to succeed transiently, the reply would be silently downgraded to a non-reply message on LINE. Consider tightening either the helper (parse data.reason / method) or the guard (e.g. only retry when the error string references the reply-target field) once you have a concrete signature for the reply-not-found variant.

@highesttt highesttt merged commit f4cc52b into main Jul 9, 2026
9 of 10 checks passed
@highesttt highesttt deleted the highest/plat-37877 branch July 9, 2026 13:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant