diff --git a/client/src/components/Weather/WeatherWidget.test.tsx b/client/src/components/Weather/WeatherWidget.test.tsx
index db6811c64..b3e5c8c8f 100644
--- a/client/src/components/Weather/WeatherWidget.test.tsx
+++ b/client/src/components/Weather/WeatherWidget.test.tsx
@@ -208,4 +208,45 @@ describe('WeatherWidget', () => {
expect(weatherApi.get).toHaveBeenCalledWith(48.86, 2.35, '2025-06-01', 'de')
expect(sessionStorage.getItem('weather_48.86_2.35_2025-06-01_de')).not.toBeNull()
})
+
+ // The day-local anchor (#2167) moves whenever the day is edited, so a single
+ // failed lookup must not keep the badge on the dash for the widget's lifetime.
+ it('FE-COMP-WEATHERWIDGET-016: clears the error dash once a new anchor resolves', async () => {
+ vi.mocked(weatherApi.get).mockRejectedValueOnce(new Error('Network error'))
+ vi.mocked(weatherApi.get).mockResolvedValue(buildWeather({ temp: 21 }))
+ useSettingsStore.setState({ settings: { ...useSettingsStore.getState().settings, temperature_unit: 'celsius' } })
+
+ const { rerender } = render()
+ await waitFor(() => {
+ expect(screen.getByText('—')).toBeInTheDocument()
+ })
+
+ rerender()
+
+ await waitFor(() => {
+ expect(screen.getByText('21°C')).toBeInTheDocument()
+ })
+ expect(screen.queryByText('—')).not.toBeInTheDocument()
+ })
+
+ it('FE-COMP-WEATHERWIDGET-017: clears the error dash when the new anchor comes from cache', async () => {
+ vi.mocked(weatherApi.get).mockRejectedValue(new Error('Network error'))
+ sessionStorage.setItem(
+ 'weather_41.9_12.5_2025-06-01_en',
+ JSON.stringify({ data: buildWeather({ temp: 24 }), fetchedAt: Date.now() }),
+ )
+ useSettingsStore.setState({ settings: { ...useSettingsStore.getState().settings, temperature_unit: 'celsius' } })
+
+ const { rerender } = render()
+ await waitFor(() => {
+ expect(screen.getByText('—')).toBeInTheDocument()
+ })
+
+ rerender()
+
+ await waitFor(() => {
+ expect(screen.getByText('24°C')).toBeInTheDocument()
+ })
+ expect(weatherApi.get).toHaveBeenCalledTimes(1)
+ })
})
diff --git a/client/src/components/Weather/WeatherWidget.tsx b/client/src/components/Weather/WeatherWidget.tsx
index d56753d68..4ee413196 100644
--- a/client/src/components/Weather/WeatherWidget.tsx
+++ b/client/src/components/Weather/WeatherWidget.tsx
@@ -63,6 +63,10 @@ export default function WeatherWidget({ lat, lng, date, compact = false, stacked
useEffect(() => {
if (!lat || !lng || !date) return
let cancelled = false
+ // Every anchor, date or language change is a fresh attempt, so a failure from
+ // the previous one must not outlive it. Since #2167 the anchor is day-local and
+ // moves with each edit, which would otherwise pin the badge on the error dash.
+ setFailed(false)
const rLat = Math.round(lat * 100) / 100
const rLng = Math.round(lng * 100) / 100
// The language is part of the key: descriptions come back localized, and the