Skip to content

Troubleshooting

Symptom: You just signed in, but API calls return 401 Token expired or 401 Invalid token.

Causes:

  • Clock skew. JWT validation checks exp (expiration) against the server’s clock. If your device’s clock is more than a few minutes off, tokens may appear expired. Sync your system clock with NTP.
  • Token copied incorrectly. Make sure you’re using the full access_token string with no trailing whitespace or line breaks.
  • Wrong header format. The header must be exactly Authorization: Bearer <access_token> — note the space after Bearer and no quotes around the token value.
  • Using the wrong token. access_token goes in the Authorization header. refresh_token is only for exchanging at POST /auth/refresh.

Fix: Verify your system clock is accurate (date -u should match UTC within a few seconds). If the clock is fine, refresh your access token (see Authentication) and confirm the Authorization header is formatted correctly.


Symptom: API calls were working, now they return 401 Token expired.

Cause: Access tokens last 1 hour. Your client needs to exchange the refresh token for a new access token before the current one expires.

Fix: Exchange your refresh token for a new access token:

Terminal window
curl -X POST https://api.hungrymachines.io/auth/refresh \
-H "Content-Type: application/json" \
-d '{"refresh_token": "YOUR_REFRESH_TOKEN"}'

The response contains a new access_token and a new refresh_token — save both, then retry your original request with the new access token. If this call itself returns 400 Invalid Refresh Token, the refresh token is expired (30-day max) — the user needs to log in again.


Symptom: POST /api/v1/readings returns 201 accepted, but GET /api/v1/schedule returns source: "defaults" with a flat comfort band and zero savings.

Cause: Hungry Machines needs about a few days of continuous readings before it can build a model of how your home responds. Until then, the schedule endpoint returns safe defaults based on your preferences and setpoint_temps is null.

What to expect:

  1. At first: source: "defaults", flat comfort band, model_confidence: null, setpoint_temps: null.
  2. After a few days: once enough continuous data has arrived, the next overnight run produces your first source: "optimization" schedule.
  3. Ongoing: Hungry Machines keeps the model current as it sees more weather and more of how your home responds.

Fix: Keep pushing readings consistently. The defaults are safe to apply — they maintain your comfort settings but won’t save energy. When source is "defaults", apply the band midpoint as your setpoint: (high_temps[idx] + low_temps[idx]) / 2. Once the model is ready, setpoint_temps becomes a 48-element array and optimized schedules appear automatically.


Symptom: source is "optimization" but the high_temps and low_temps arrays have little variation — they look almost flat.

Causes:

  • Savings level 1 (tight). With a ±2°F band, the optimizer has very little room to shift loads. Try increasing to savings level 2 (±6°F) or 3 (±12°F) via PUT /api/v1/preferences.
  • Flat rate plan. If your utility charges the same rate all day, there’s no price signal to optimize against. The optimizer works best with time-of-use (TOU) or real-time pricing.
  • Mild weather. When outdoor and indoor temps are close, the HVAC runs very little and there’s less to optimize.

Fix: Check your savings_level and optimization_mode in preferences. If you’re on a flat-rate plan, the optimizer may not produce significant schedule variation — that’s expected behavior, not a bug. You can inspect (and override) the rate curve the optimizer is using via GET / PUT /api/v1/rates — submitting your own 24-hour curve is the fastest way to give the optimizer a price signal to work with.


Symptom: POST /api/v1/appliances returns 403 Upgrade required.

Cause: Free-tier accounts are limited to one HVAC appliance. You’ll get a 403 if you try to:

  • Register a second appliance (any type)
  • Register a non-HVAC device (EV charger, home battery, water heater)

Fix: Upgrade to Premium via the dashboard at hungrymachines.io/dashboard. Premium accounts can register unlimited appliances of any type.


Symptom: POST /api/v1/readings returns 429 Rate limit exceeded.

Cause: The daily reading ceiling is a runaway-loop safeguard, not a normal-use limit. It scales with how many appliances you run — at 5-minute intervals a single HVAC generates ~288 readings/day, comfortably under the cap. Large catch-up batches after an outage, or an uncoordinated set of sensors all pushing at once, can trip it.

Fix: Push on a steady cadence rather than in bursts. If you’re catching up after an outage, spread the backfill out or trim to the most recent readings. If you legitimately run several appliances, tag each reading with its appliance_id — the ceiling scales with your active appliance count.


If none of the above resolves your issue: