Hub returns 401 Unauthorized
Applies to: core, hub
Symptom
Core logs show requests to the HubHubThe Go service that owns background processing, integrations, and the admin API. Sibling to Core. rejected:
POST http://hivecfm-hub-api:8080/v1/feedback-records 401 (Unauthorized)
{"error":"Missing Authorization header"}
{"error":"Invalid Authorization header format. Expected: Bearer <api-key>"}A direct curl with no credentials reproduces it:
curl -i http://localhost:8090/v1/feedback-records
# HTTP/1.1 401 UnauthorizedLikely cause
The HubHubThe Go service that owns background processing, integrations, and the admin API. Sibling to Core. authenticates every /v1/* request with middleware.Auth(cfg.APIKey) — it expects:
Authorization: Bearer <api-key>…where <api-key> matches the HubHubThe Go service that owns background processing, integrations, and the admin API. Sibling to Core.’s API_KEY env var exactly. A 401 means one of:
- Keys drifted.
API_KEYinhivecfm-hub/.envdoes not equalHIVECFM_HUB_API_KEYinhivecfm-core/.env(or.env.local). - No
Authorizationheader. Core was pointed at the Hub but not given the key (empty env var). - Wrong header shape. Something is sending the raw key instead of
Bearer <key>.
Fix
Read both sides of the key
grep '^API_KEY=' /home/ubuntu/AG-DEV/hivecfm-hub/.env
grep '^HIVECFM_HUB_API_KEY=' /home/ubuntu/AG-DEV/hivecfm-core/.env
grep '^HIVECFM_HUB_API_KEY=' /home/ubuntu/AG-DEV/hivecfm-core/.env.local 2>/dev/nullThe values must be identical strings. If .env.local exists, it wins for native dev.
Fix the mismatch
Pick one value and write it on both sides:
# In hivecfm-hub/.env
API_KEY=hivecfm-hub-secret-key
# In hivecfm-core/.env (and .env.local if present)
HIVECFM_HUB_API_KEY=hivecfm-hub-secret-key
HIVECFM_HUB_URL=http://hivecfm-hub-api:8080 # Docker
# or HIVECFM_HUB_URL=http://localhost:8090 # native devHub-side env var is API_KEY; core-side env var is HIVECFM_HUB_API_KEY. The names are different on purpose — same secret, two config files.
Restart both services
# Docker
docker compose restart hivecfm-hub-api hivecfm-core
# Native dev
# Stop pnpm dev / `make run` and start them againSmoke-test from the shell
curl -i -H "Authorization: Bearer $API_KEY" \
http://localhost:8090/v1/feedback-records
# expect 200 (or 404 with a JSON body), not 401Verify
- Core logs no longer show
401when calling the Hub. curl -i http://localhost:8090/healthreturns200with no auth header (health is public).curl -i -H "Authorization: Bearer <key>" http://localhost:8090/v1/webhooksreturns200or the expected JSON payload.
Prevent
- Treat the Hub key as one secret with two names — change it in
hivecfm-hub/.envandhivecfm-core/.envtogether, never one at a time. - The Hub will refuse to start with an empty
API_KEY; if Hub is healthy, the key is set — the bug is on the caller side. - When rotating keys in shared environments, restart both services in the same window to avoid a window where one side still holds the old value.