Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@

## [Unreleased]

### Changed

- Removing a provider key now surfaces the server's specific CSRF rejection reason ("Session expired - reload the page", "Cross-origin mismatch - check reverse proxy headers", or the fallback "Cross-origin request rejected") when the underlying POST is rejected with 403, instead of swallowing all three into one generic toast. (Refs #2572)

## [v0.51.137] — 2026-05-25 — Release DI (stage-batch19 — 6-PR medium-risk batch)

### Added
Expand Down
14 changes: 13 additions & 1 deletion static/panels.js
Original file line number Diff line number Diff line change
Expand Up @@ -6874,7 +6874,19 @@ async function _removeProviderKey(providerId){
if(els.saveBtn){els.saveBtn.disabled=false;els.saveBtn.textContent=t('providers_save');}
}
}catch(e){
showToast('Error: '+e.message);
// A 403 from /api/providers/delete fires when the CSRF cookie/header
// pair has drifted. The server distinguishes three reasons in
// api/routes.py:_csrf_rejection_error ("Session expired - reload the
// page", "Cross-origin mismatch - check reverse proxy headers", and
// the fallback "Cross-origin request rejected"); api()'s catch lifts
// that string onto e.message. Pass it through verbatim so the
// deployment-shape failure #2572 calls out keeps its actionable hint
// instead of being flattened to a single generic toast.
if(e&&e.status===403){
showToast(e.message||'Session expired. Reload the page and try again.',6000,'error');
}else{
showToast('Error: '+e.message);
}
if(els.saveBtn){els.saveBtn.disabled=false;els.saveBtn.textContent=t('providers_save');}
}
}
Expand Down
Loading