Nobody has started this yet — be first.
Business impact
The entire reason this project's cache/stale-fallback design exists is so a real-world upstream hiccup degrades gracefully (stale data with a warning, or a clear per-city error) instead of taking down the whole request. Right now, any upstream failure for any city -- a timeout, a 404, a 5xx, rate-limiting, anything -- instead causes a nil-pointer panic while handling that city's result. The panic-recovery middleware catches it and turns it into a generic 500, so the process doesn't crash outright -- but every single upstream failure, for any reason, now surfaces as an opaque server error to the client instead of the carefully-designed stale/error response this project's own README describes as its core resilience feature. Under any real, non-trivial outage window, this makes the dashboard endpoint essentially unusable exactly when its fallback behavior matters most.
Problem
fetchOne is supposed to cache the fetched data only when the upstream call actually succeeded -- but the call that stores the result into the cache now runs unconditionally, before checking whether the fetch actually returned an error. On the failure path, the fetched data pointer is nil, and dereferencing it to store into the cache panics.
Current behavior
Any per-city upstream failure -- a timeout, a 404, a 5xx, rate-limiting -- panics with a nil-pointer dereference inside fetchOne instead of returning the intended stale/error CityResult; GET /dashboard surfaces it as a bare 500 via the panic-recovery middleware.
Expected behavior
The cache is only updated on a successful fetch; on failure, fetchOne proceeds directly to its existing stale-fallback / per-city-error logic (both of which are still correct and untouched), without ever touching the cache.
Steps to reproduce
Configure a fetch for a city with no prior cache entry, using a fake provider that returns an error. fetcher.FetchAll(ctx, []string{"Atlantis"})
Why this matters
This is exactly the "no panics anywhere, including on... an unexpected nil" production-scale bar this project's own README calls out explicitly -- a cache-write that got moved earlier in the function (perhaps during a refactor) without also moving its success-only guard is a realistic, easy mistake: nothing about a cache write "looks" conditional at a glance, so it's easy to reorder code around it without noticing the guard needs to move too.
Suggested approach
Look at where f.cache.Set(...) is called in fetchOne relative to where the fetch's returned error is actually checked -- compare it against the two branches immediately below (stale fallback, per-city error), which correctly only run on the failure path.
Acceptance criteria
Verification
go test ./practicetickets/... -run TestTicket09 -v
Hints (0/2)
Try it without hints first — the reading is the exercise.
Working on this ticket
Work on a branch named for the ticket — that's what you'll submit.
Branch off your fork
$git checkout -b fix/cache-set-panicFix it and commit
Meet every acceptance criterion, and add a test that would have caught this.
Push the branch
$git push -u origin fix/cache-set-panicSubmit it below
Paste your fork URL and the branch name, with a short write-up of the root cause.
Questions
Ask about anything unclear in the ticket — the maintainer and anyone who has solved it can answer. Please don't post full solutions.
Sign in to ask a question or reply.
Sign inweather_dashboarddbappmockweatherWEATHER_API_BASE_URL=https://api.openweathermap.orgWEATHER_API_KEYdocker-compose.prod.ymlRun the project's own test suite:
make test # go test ./...
make test-race # go test -race ./... (includes the concurrency/partial-failure test)
Work the tickets in PRACTICE_TICKETS.md (TICKET-01 through TICKET-10); each names one Go test in practicetickets/:
./practice_tickets_run.sh # all 10, pass/fail summary
go test ./practicetickets/... -run TestTicket01 -v # a single ticket
go test -race ./practicetickets/... -run TestTicket10 -v # ticket 10 needs -race to observe its bug
Tickets 03, 04, 05, and 06 touch the saved-cities Postgres store and need a reachable test database, set via WD_TEST_DATABASE_URL (defaults to postgres://postgres:postgres@localhost:5436/weather_dashboard_test if unset). Tickets 01, 02, 07, 08, 09, and 10 need no database at all.
Level 1
Fix a bug
Read existing behaviour, correct it.