Skip to content

fix(auth): avoid logout on license activation errors#602

Merged
s0up4200 merged 1 commit intomainfrom
fix/auth-license-activation-errors
Nov 18, 2025
Merged

fix(auth): avoid logout on license activation errors#602
s0up4200 merged 1 commit intomainfrom
fix/auth-license-activation-errors

Conversation

@s0up4200
Copy link
Collaborator

@s0up4200 s0up4200 commented Nov 18, 2025

qui would logout on license activation errors due to shared status codes

Summary by CodeRabbit

  • Bug Fixes
    • Improved API error message handling with clearer error feedback to users
    • Enhanced session expiry detection with automatic redirect to login
    • Better support for empty API responses

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 18, 2025

Walkthrough

The API client introduces centralized error handling by extracting error messages from responses and delegating authentication errors to a new handler, replacing per-endpoint redirect logic. Empty responses are now handled by returning undefined. Four private helper methods manage error extraction, auth error handling, logout determination, and auth-endpoint identification.

Changes

Cohort / File(s) Summary
Centralized Error Handling
web/src/lib/api.ts
Added extractErrorMessage() to parse JSON/text error bodies with fallbacks. Added handleAuthError() to manage session expiry redirects. Added shouldForceLogout() to conditionally determine logout necessity. Added isAuthCheckEndpoint() to identify auth endpoints. Integrated these into error flows including empty response handling (204, content-length 0) and updated exportTorrent error handling.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant ApiClient
    participant Server
    participant ErrorHandler
    participant Router

    Client->>ApiClient: fetch(endpoint)
    ApiClient->>Server: HTTP request
    
    alt Success Response
        Server-->>ApiClient: 200 OK / Data
        ApiClient->>Client: Return data
    else Empty Response
        Server-->>ApiClient: 204 / Content-Length: 0
        ApiClient->>Client: Return undefined
    else Error Response
        Server-->>ApiClient: Non-OK status
        ApiClient->>ApiClient: extractErrorMessage()
        ApiClient->>ApiClient: shouldForceLogout(status, endpoint, message)
        
        alt Auth Error Detected
            ApiClient->>ErrorHandler: handleAuthError(status, endpoint, message)
            ErrorHandler->>Router: Redirect to login
            ErrorHandler-->>ApiClient: Throw error
        else Other Error
            ApiClient-->>Client: Throw error with message
        end
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Auth error logic: Review shouldForceLogout() conditions for status codes, endpoints, and path-based decisions to ensure proper session expiry detection.
  • Error message extraction: Verify extractErrorMessage() handles malformed JSON, missing content-type headers, and edge cases gracefully.
  • Endpoint classification: Confirm isAuthCheckEndpoint() correctly identifies auth-check endpoints and their use in logout logic.
  • Integration points: Trace error handling changes in exportTorrent() and other affected methods to ensure consistent behavior.

Poem

🐰 A rabbit hops through API calls,
Where errors once scattered down halls,
Now centralized and neat,
The handlers compete,
To catch every auth session's falls!

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main fix: preventing logout on license activation errors, which directly aligns with the PR's objective.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/auth-license-activation-errors

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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
web/src/lib/api.ts (1)

116-142: extractErrorMessage is robust; consider optional support for additional fields

This helper is nicely defensive: it handles empty bodies, JSON with error/message, plain-text bodies, and falls back to a generic status string without risking double body reads.

If your backend ever emits error details under other keys (e.g. detail or nested errors[0].message), you could extend the JSON parsing to check those as well, but that’s purely optional and can be added when needed.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cd6db45 and 08f625a.

📒 Files selected for processing (1)
  • web/src/lib/api.ts (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
web/src/lib/api.ts (1)
web/src/lib/base-url.ts (1)
  • withBasePath (24-29)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Run tests
🔇 Additional comments (2)
web/src/lib/api.ts (2)

103-114: Centralized error handling and empty-response handling in request look good

Wiring extractErrorMessage and handleAuthError into request is clean and gives you a single place to manage auth vs. non-auth failures. Treating 204 / content-length: "0" as undefined also pairs nicely with callers like getLatestVersion that already do response ?? null.

No issues from my side here.


1045-1047: Reusing shared auth/error handling in exportTorrent is a good improvement

Hooking exportTorrent into extractErrorMessage + handleAuthError makes its error behavior consistent with the rest of the client, including proper session-expiry redirects and better error messages for other failures. The explicit endpoint string you pass into handleAuthError also ensures isAuthCheckEndpoint and future endpoint-based checks behave predictably.

Looks good as-is.

@s0up4200 s0up4200 merged commit 240b40d into main Nov 18, 2025
17 checks passed
@s0up4200 s0up4200 deleted the fix/auth-license-activation-errors branch November 18, 2025 08:11
alexlebens pushed a commit to alexlebens/infrastructure that referenced this pull request Dec 3, 2025
This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [ghcr.io/autobrr/qui](https://github.com/autobrr/qui) | minor | `v1.7.0` -> `v1.8.1` |

---

### Release Notes

<details>
<summary>autobrr/qui (ghcr.io/autobrr/qui)</summary>

### [`v1.8.1`](https://github.com/autobrr/qui/releases/tag/v1.8.1)

[Compare Source](autobrr/qui@v1.8.0...v1.8.1)

#### Changelog

##### Bug Fixes

- [`61c87e1`](autobrr/qui@61c87e1): fix(torznab): use detached context for indexer tests ([#&#8203;659](autobrr/qui#659)) ([@&#8203;s0up4200](https://github.com/s0up4200))

**Full Changelog**: <autobrr/qui@v1.8.0...v1.8.1>

#### Docker images

- `docker pull ghcr.io/autobrr/qui:v1.8.1`
- `docker pull ghcr.io/autobrr/qui:latest`

#### What to do next?

- Join our [Discord server](https://discord.autobrr.com/qui)

Thank you for using qui!

### [`v1.8.0`](https://github.com/autobrr/qui/releases/tag/v1.8.0)

[Compare Source](autobrr/qui@v1.7.0...v1.8.0)

#### Changelog

##### New Features

- [`6903812`](autobrr/qui@6903812): feat(crossseed): batch torrent file lookups end-to-end ([#&#8203;625](autobrr/qui#625)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`336ce48`](autobrr/qui@336ce48): feat(crossseed): persist seeded search settings ([#&#8203;618](autobrr/qui#618)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`7b0b292`](autobrr/qui@7b0b292): feat(docker): add curl to Dockerfiles ([#&#8203;570](autobrr/qui#570)) ([@&#8203;onedr0p](https://github.com/onedr0p))
- [`91e1677`](autobrr/qui@91e1677): feat(filters): default-hide empty status/category/tag groups ([#&#8203;581](autobrr/qui#581)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`f07bb8d`](autobrr/qui@f07bb8d): feat(header): add missing links to header burger menu ([#&#8203;624](autobrr/qui#624)) ([@&#8203;nuxencs](https://github.com/nuxencs))
- [`ee4c16b`](autobrr/qui@ee4c16b): feat(instances): allow disabling qbit instances ([#&#8203;582](autobrr/qui#582)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`477db14`](autobrr/qui@477db14): feat(search): column filters ([#&#8203;633](autobrr/qui#633)) ([@&#8203;nuxencs](https://github.com/nuxencs))
- [`cd6db45`](autobrr/qui@cd6db45): feat(themes): add basic variation support ([#&#8203;569](autobrr/qui#569)) ([@&#8203;jabloink](https://github.com/jabloink))
- [`979a0d4`](autobrr/qui@979a0d4): feat(torrents): add clear filters action for empty filtered state ([#&#8203;627](autobrr/qui#627)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`e06acb7`](autobrr/qui@e06acb7): feat(torrents): add cross-seeding and search ([#&#8203;553](autobrr/qui#553)) ([@&#8203;KyleSanderson](https://github.com/KyleSanderson))
- [`95cef23`](autobrr/qui@95cef23): feat(torrents): add reannounce monitor ([#&#8203;606](autobrr/qui#606)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`098fdb0`](autobrr/qui@098fdb0): feat(torrents): add rename functionality in TorrentDetailsPanel ([#&#8203;590](autobrr/qui#590)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`6e8fdbd`](autobrr/qui@6e8fdbd): feat(torrents): implement drag-and-drop file upload to add torrents ([#&#8203;568](autobrr/qui#568)) ([@&#8203;dthinhle](https://github.com/dthinhle))
- [`9240545`](autobrr/qui@9240545): feat(ui): add dense view mode for compact table display ([#&#8203;643](autobrr/qui#643)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`77fad15`](autobrr/qui@77fad15): feat(ui): improve torrent details panel file tree and rename UX ([#&#8203;650](autobrr/qui#650)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`8b1e70e`](autobrr/qui@8b1e70e): feat(web): Use original qBittorrent status names ([#&#8203;595](autobrr/qui#595)) ([@&#8203;FibreTTP](https://github.com/FibreTTP))
- [`01dd553`](autobrr/qui@01dd553): feat(web): show listening port in connectable status tooltip ([#&#8203;635](autobrr/qui#635)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`3140739`](autobrr/qui@3140739): feat: make tracker icon column sortable ([#&#8203;513](autobrr/qui#513)) ([@&#8203;s0up4200](https://github.com/s0up4200))

##### Bug Fixes

- [`240b40d`](autobrr/qui@240b40d): fix(auth): avoid logout on license activation errors ([#&#8203;602](autobrr/qui#602)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`7185408`](autobrr/qui@7185408): fix(backups): do not persist ZIPs to disk ([#&#8203;632](autobrr/qui#632)) ([@&#8203;KyleSanderson](https://github.com/KyleSanderson))
- [`de0e00a`](autobrr/qui@de0e00a): fix(content): use Hints for detection ([#&#8203;621](autobrr/qui#621)) ([@&#8203;KyleSanderson](https://github.com/KyleSanderson))
- [`5f016a8`](autobrr/qui@5f016a8): fix(cross): performance improvements ([#&#8203;629](autobrr/qui#629)) ([@&#8203;KyleSanderson](https://github.com/KyleSanderson))
- [`82c74ba`](autobrr/qui@82c74ba): fix(crossseed): flip deduplication to maps ([#&#8203;622](autobrr/qui#622)) ([@&#8203;KyleSanderson](https://github.com/KyleSanderson))
- [`b78a079`](autobrr/qui@b78a079): fix(crossseed): inherit TMM state from matched torrent ([#&#8203;654](autobrr/qui#654)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`2438fc6`](autobrr/qui@2438fc6): fix(crossseed): process full RSS feeds ([#&#8203;615](autobrr/qui#615)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`6f57090`](autobrr/qui@6f57090): fix(database): do not release mutex on tx err ([#&#8203;571](autobrr/qui#571)) ([@&#8203;KyleSanderson](https://github.com/KyleSanderson))
- [`74509d4`](autobrr/qui@74509d4): fix(incognito): prevent categories leaking ([#&#8203;592](autobrr/qui#592)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`f08eff2`](autobrr/qui@f08eff2): fix(instances): support empty username for localhost bypass ([#&#8203;575](autobrr/qui#575)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`cd3caaf`](autobrr/qui@cd3caaf): fix(license): cap 7d offline grace, ignore transient errors ([#&#8203;617](autobrr/qui#617)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`59c747b`](autobrr/qui@59c747b): fix(reannounce): validate number fields and show min hints ([#&#8203;613](autobrr/qui#613)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`f6bd1e6`](autobrr/qui@f6bd1e6): fix(themes): correct Nightwalker description from purple to blue ([#&#8203;648](autobrr/qui#648)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`2b641c5`](autobrr/qui@2b641c5): fix(torznab): filter Prowlarr autodiscovery to enabled torrent indexers ([#&#8203;638](autobrr/qui#638)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`1995783`](autobrr/qui@1995783): fix(ui): improve cross-seed mobile responsiveness ([#&#8203;647](autobrr/qui#647)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`b83aebe`](autobrr/qui@b83aebe): fix(web): align CrossSeedDialog indexers with search flows ([#&#8203;619](autobrr/qui#619)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`3b60821`](autobrr/qui@3b60821): fix(web): indent subcategories in SetCategoryDialog ([#&#8203;636](autobrr/qui#636)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`82850cd`](autobrr/qui@82850cd): fix: glob pattern formatting in tooltip content ([#&#8203;579](autobrr/qui#579)) ([@&#8203;onedr0p](https://github.com/onedr0p))

##### Other Changes

- [`c20bc0a`](autobrr/qui@c20bc0a): build(vite): enable default minification ([#&#8203;574](autobrr/qui#574)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`ceac8ca`](autobrr/qui@ceac8ca): chore(ci): upgrade Claude Code workflow to Opus 4.5 ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`9d6c10e`](autobrr/qui@9d6c10e): chore(deps): bump actions/checkout from 5 to 6 in the github group ([#&#8203;628](autobrr/qui#628)) ([@&#8203;dependabot](https://github.com/dependabot)\[bot])
- [`f5704de`](autobrr/qui@f5704de): chore(deps): bump golang.org/x/crypto from 0.43.0 to 0.45.0 ([#&#8203;611](autobrr/qui#611)) ([@&#8203;dependabot](https://github.com/dependabot)\[bot])
- [`0aae9aa`](autobrr/qui@0aae9aa): chore(deps): bump the golang group with 3 updates ([#&#8203;546](autobrr/qui#546)) ([@&#8203;dependabot](https://github.com/dependabot)\[bot])
- [`0d97087`](autobrr/qui@0d97087): chore(themes): add crypto instructions in-app ([#&#8203;620](autobrr/qui#620)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`e778865`](autobrr/qui@e778865): docs(funding): add donation methods and crypto addresses ([#&#8203;583](autobrr/qui#583)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`563645c`](autobrr/qui@563645c): docs: update qui image ([#&#8203;655](autobrr/qui#655)) ([@&#8203;s0up4200](https://github.com/s0up4200))

**Full Changelog**: <autobrr/qui@v1.7.0...v1.8.0>

#### Docker images

- `docker pull ghcr.io/autobrr/qui:v1.8.0`
- `docker pull ghcr.io/autobrr/qui:latest`

#### What to do next?

- Join our [Discord server](https://discord.autobrr.com/qui)

Thank you for using qui!

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi41LjAiLCJ1cGRhdGVkSW5WZXIiOiI0Mi41LjAiLCJ0YXJnZXRCcmFuY2giOiJtYWluIiwibGFiZWxzIjpbImltYWdlIl19-->

Reviewed-on: https://gitea.alexlebens.dev/alexlebens/infrastructure/pulls/2211
Co-authored-by: Renovate Bot <renovate-bot@alexlebens.net>
Co-committed-by: Renovate Bot <renovate-bot@alexlebens.net>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant