# weatherapi Troubleshooting Use this guide to separate startup, database, template, request-validation, and no-data problems. For full command and configuration reference, see [`docs/cli.md`](cli.md) and [`docs/config.md`](config.md). ## Startup Fails with `load config` Symptom: the process exits and logs `weatherapi failed: load config: ...`. Likely causes: - the config path is wrong; - the process working directory is not where `config.yml` is expected; - YAML syntax is invalid; - required feedapi config fields are missing. Diagnostic: ```sh ls -l config.yml python3 -c 'import yaml; yaml.safe_load(open("config.yml"))' ``` Safe fix: pass the intended file explicitly with `-config`, or set a non-blank `WEATHERAPI_CONFIG`. Fix YAML syntax and compare the file with [`examples/config.minimal.yml`](../examples/config.minimal.yml). ## Startup Fails with `config.databases requires at least one entry` Symptom: the process exits before opening any database. Likely cause: `databases` is missing or empty in the YAML file. Diagnostic: ```sh rg -n '^databases:' config.yml ``` Safe fix: add at least one database entry. The first entry is the primary weather data store used for reads. ## Startup Fails with `open databases` Symptom: the process exits while opening configured database handles. Likely causes: - PostgreSQL host or port is unreachable; - credentials are invalid; - the database name in `uri` is wrong; - TLS/`sslmode` settings do not match the server; - the configured driver is not usable for this deployment. Diagnostic: ```sh psql 'postgres://USER:PASSWORD@HOST:5432/DBNAME?sslmode=disable' -c 'select 1' ``` Safe fix: correct `uri`, `username`, `password`, network routing, firewall rules, or TLS settings. Keep production secrets out of committed config files. ## Startup Fails with `select primary database` Symptom: databases open, then the process exits selecting the primary database. Likely cause: feedapi opened a registry that does not contain the first configured database name. Diagnostic: inspect the first `databases` item in the active config and verify that `name` is present and non-empty. Safe fix: give the first database entry a stable `name` and keep it as the weather database entry. ## Startup Fails with `build app` Symptom: the process exits after database setup but before serving HTTP. Likely causes: - feedapi cannot construct the HTTP app from the config; - renderer or template setup failed; - endpoint registration failed. Diagnostic: read the error text after `build app:`. If the error mentions templates, inspect `templates.base_dir`. Safe fix: correct the config value mentioned by the error. For template errors, make the directory readable and ensure the repository's `*.txt.tmpl` files are present. ## Requests Return `400 invalid_parameter` Symptom: JSON error body includes: ```json { "error": { "code": "invalid_parameter", "message": "..." } } ``` Likely causes: - unknown query parameter; - `precision` outside `0` through `2`, or not an integer; - `precision` used on alerts, discussions, or weather stories; - `tz` used on observations, current conditions, or alerts; - invalid timezone value; - both `tz` and `TZ` are present with different values. Diagnostic: compare the request against the route's query parameters in [`docs/api.md`](api.md). Reproduce with `curl -i` to see the status and body. Safe fix: remove unsupported parameters or correct values. Use `tz=Chicago`, `tz=America/Chicago`, a supported US abbreviation, or an offset such as `TZ=-5` on routes that accept timezone selection. ## Requests Return `406 unsupported_format` Symptom: the response status is `406 Not Acceptable` and the error code is `unsupported_format`. Likely causes: - `format` has a value other than `json`, `xml`, or `text`; - the `Accept` header cannot be matched to a registered renderer; - the configured default format is unsupported. Diagnostic: ```sh curl -i 'http://localhost:8080/observations?format=json' curl -i -H 'Accept: application/json' 'http://localhost:8080/observations' ``` Safe fix: request `format=json`, `format=xml`, or `format=text`, or set `server.default_format` to a supported value. ## Text Responses Fail or Do Not Render Expected Text Symptom: `format=text` fails, returns an error, or does not contain expected endpoint text. Likely causes: - `templates.base_dir` points to the wrong directory; - templates were not copied into the runtime container or deployment directory; - file permissions prevent reading templates; - a customized template has invalid syntax. Diagnostic: ```sh find templates -maxdepth 1 -name '*.txt.tmpl' -print | sort curl -i 'http://localhost:8080/forecast/hourly?format=text' ``` Safe fix: restore the repository's `templates/` directory or update `templates.base_dir` to the mounted template path. In the Docker image, the default template directory is `/weatherapi/templates`. ## Successful Response Has `data: null` Symptom: the response is `200 OK`, but JSON contains `"data": null`. Likely causes: - weatherfeeder has not populated the relevant table yet; - the relevant latest row does not exist after a database restore; - the service is pointed at an empty or wrong database; - current conditions have no observations in the implemented 30-minute window. Diagnostic: ```sh curl -s 'http://localhost:8080/observations?format=json' curl -s 'http://localhost:8080/conditions/current?format=json' ``` Safe fix: verify weatherfeeder is running and writing to the same database that `weatherapi` uses as its first configured database. For current conditions, wait for recent observations or inspect weatherfeeder ingestion. ## Forecast Day Routes Return Empty `periods` Symptom: `/forecast/hourly/today`, `/forecast/hourly/tomorrow`, `/forecast/narrative/today`, or `/forecast/narrative/tomorrow` returns a forecast object with an empty `periods` array. Likely causes: - no period `startTime` falls on that calendar day in the selected timezone; - the request omitted `tz`, so UTC day boundaries were used; - the stored forecast is stale. Diagnostic: ```sh curl -s 'http://localhost:8080/forecast/hourly/today?tz=America/Chicago' curl -s 'http://localhost:8080/forecast/hourly?tz=America/Chicago' ``` Safe fix: provide the intended `tz` value and verify the unfiltered forecast contains periods for the expected local date. ## Timezone Errors Symptom: requests with `tz` or `TZ` return `400 invalid_parameter`. Likely causes: - the timezone is not an IANA location, supported US abbreviation, supported alias, or valid UTC offset; - an offset is outside `-14:00` through `+14:00`; - both `tz` and `TZ` are present but do not match case-insensitively. Diagnostic: ```sh curl -i 'http://localhost:8080/forecast/hourly?tz=not-a-timezone' curl -i 'http://localhost:8080/forecast/hourly?tz=CDT&TZ=EST' ``` Safe fix: use one timezone parameter. Known-good examples include `tz=America/Chicago`, `tz=Chicago`, `tz=CDT`, and `TZ=-5`. ## Precision Errors Symptom: requests with `precision` return `400 invalid_parameter`. Likely causes: - value is not an integer; - value is less than `0` or greater than `2`; - route does not accept `precision`. Diagnostic: ```sh curl -i 'http://localhost:8080/conditions/current?precision=3' curl -i 'http://localhost:8080/alerts/active?precision=1' ``` Safe fix: use `precision=0`, `precision=1`, or `precision=2` only on observations, current conditions, and forecast routes. ## Missing or Stale Weather Data Symptom: responses are successful but older than expected, or endpoint families are empty. Likely causes: - weatherfeeder is stopped or failing; - weatherfeeder writes to a different database than `weatherapi` reads; - a restore or deployment changed database credentials; - upstream provider ingestion is delayed outside `weatherapi`. Diagnostic: inspect weatherfeeder logs and query the configured Postgres database directly for recent rows in the relevant weatherfeeder tables. Safe fix: repair weatherfeeder ingestion or database routing. Restart `weatherapi` only when config or database connectivity changed. ## Related Docs - [`docs/api.md`](api.md): endpoint contract, query parameters, errors - [`docs/config.md`](config.md): YAML fields and examples - [`docs/operations.md`](operations.md): runtime and recovery boundaries