# Weatherreporter Troubleshooting This guide lists recurring failures with likely causes, diagnostics, and safe fixes. See [CLI reference](cli.md), [Configuration reference](config.md), and [Operations guide](operations.md) for normal usage. ## `weather_api.base_url is required` Symptom: a generation command fails before collecting weather data. Likely cause: no Weather API base URL is configured. Diagnostic: ```sh weatherreporter generate daily --config ./config.yml --date 2026-05-29 ``` Safe fix: add `weather_api.base_url` to the config file, or pass the intended config path with `--config`. Relevant docs: [Configuration reference](config.md). ## `weather_api.base_url must be an absolute URL` Symptom: config loading fails with a base URL validation error. Likely cause: `weather_api.base_url` is missing a scheme or host. Diagnostic: inspect the configured value in the file passed to `--config`. Safe fix: use an absolute URL such as `https://weather.api.example.com/`. Relevant docs: [Configuration reference](config.md). ## Invalid Timezone Symptom: config loading fails with `weather_api.timezone` context, or a CLI timezone override fails. Likely cause: `weather_api.timezone` or `--tz` is not recognized. Diagnostic: ```sh weatherreporter generate daily --tz America/Chicago --date 2026-05-29 ``` Safe fix: use an accepted timezone value, such as an IANA timezone name, `Chicago`, `Stl`, a US timezone abbreviation, or a UTC offset. Relevant docs: [Configuration reference](config.md). ## Storm Command Rejects Time Bounds Symptom: `generate storm` fails with `requires --start`, `requires --end`, or `requires --end after --start`. Likely cause: the manual event window is missing or invalid. Diagnostic: ```sh weatherreporter generate storm --start 2026-05-29T18:00 --end 2026-05-30T06:00 ``` Safe fix: provide both bounds. Use `YYYY-MM-DDTHH:MM` in the configured timezone, or RFC3339 timestamps with explicit offsets. Relevant docs: [CLI reference](cli.md). ## Weather API Fetch Fails Symptom: generation fails with `fetch /...`, an HTTP status, or request context. Likely cause: the configured Weather API endpoint is unreachable, returned a non-2xx response, or returned an invalid response envelope. Diagnostic: ```sh weatherreporter generate daily --config ./config.yml --date 2026-05-29 ``` Safe fix: verify `weather_api.base_url`, network access, and the Weather API service response. The adapter fetches `/observations`, `/conditions/current`, `/forecast/hourly`, `/forecast/narrative`, `/alerts/active`, and `/discussion`. Relevant docs: [Configuration reference](config.md). ## Hourly Forecast Is Missing Symptom: generation fails with hourly forecast context, such as missing hourly data or an hourly forecast containing no periods. Likely cause: hourly forecast data is required for generated reports. Diagnostic: check the Weather API response for `/forecast/hourly`. Safe fix: restore hourly forecast data at the Weather API. Missing-source policy cannot make hourly optional. Relevant docs: [Configuration reference](config.md), [Operations guide](operations.md). ## Source Warnings Appear Symptom: generation succeeds, but metadata or `inspect sources` shows source warnings. Likely cause: an optional source was missing or malformed under a warning missing-source policy. Diagnostic: ```sh weatherreporter inspect sources RUN_ID weatherreporter inspect metadata RUN_ID ``` Safe fix: inspect the warning `source`, `code`, `message`, and `endpoint`. Fix the upstream optional source, or intentionally change the relevant `missing_source` policy. Relevant docs: [Configuration reference](config.md), [Operations guide](operations.md). ## `scriptorium` Is Not Found Or Cannot Start Symptom: generation fails with `run scriptorium render` or `run scriptorium` and an executable or OS error. Likely cause: the configured Scriptorium binary is unavailable or not executable. Diagnostic: check `scriptorium.binary` in config and run the same binary outside `weatherreporter`. Safe fix: install Scriptorium, update `scriptorium.binary`, or fix executable permissions. Relevant docs: [Configuration reference](config.md), [Scriptorium integration](integrations/scriptorium.md). ## Render Preflight Fails Symptom: generation fails with `scriptorium render exited with code ...`. Likely cause: Scriptorium rejected the prompt, config, profile, or `data_package` input before report generation. Diagnostic: ```sh weatherreporter inspect metadata RUN_ID weatherreporter inspect data-package RUN_ID ``` Then read the preflight path from metadata. It contains captured stdout, stderr, exit code, and command. Safe fix: fix the Scriptorium configuration, prompt ID, profile, or data package input indicated by stderr. Relevant docs: [Operations guide](operations.md), [Scriptorium integration](integrations/scriptorium.md). ## Scriptorium Run Fails Symptom: generation fails with `scriptorium run exited with code ...`. Likely cause: Scriptorium failed during report generation or validation. Diagnostic: ```sh weatherreporter inspect metadata RUN_ID weatherreporter inspect data-package RUN_ID ``` If metadata includes a rendered report path, inspect that report as well. A nonzero run can still leave a managed report artifact. Safe fix: use the captured stderr and data package to fix the Scriptorium prompt, profile, model configuration, or validation issue. Relevant docs: [Operations guide](operations.md), [Scriptorium integration](integrations/scriptorium.md). ## Generated Text Validation Fails Symptom: Daily, Today, Tomorrow, or Hourly generation fails with generated-text decode, unknown-field, required-field, or multiple-JSON-values context. Likely cause: Scriptorium wrote structured JSON that does not match the GeneratedText contract for the selected report. Diagnostic: ```sh weatherreporter inspect metadata RUN_ID ``` Then inspect the generated-text raw path recorded in metadata, if present. Safe fix: update the Scriptorium prompt or schema configuration so the prompt writes the expected structured JSON for the report. Relevant docs: [Operations guide](operations.md), [Generated Text internals](internal/generatedtext.md), [Scriptorium integration](integrations/scriptorium.md). ## Template Rendering Fails Symptom: Daily, Today, Tomorrow, or Hourly generation fails with report template parsing or execution context after generated text validation succeeds. Likely cause: an embedded template references a missing context field or receives a value shape that does not match its typed render context. Diagnostic: ```sh weatherreporter inspect metadata RUN_ID ``` If metadata records generated-text and render-context paths, inspect those artifacts along with the template named by the report definition. Safe fix: update the embedded template or render-context builder so the template uses the implemented typed context. Relevant docs: [Report Templates](templates.md), [Report Template internals](internal/reporttemplate.md). ## Batch Command Returns Nonzero Symptom: `run morning` or `run evening` returns nonzero. Likely cause: weather collection failed before planning, or at least one planned report failed after planning succeeded, or every report succeeded but the top-level batch distributor notification failed. Diagnostic: if stdout contains a JSON summary, inspect each failed report item and the top-level `notification` object. Stderr includes one `batchNotification` line when batch notification is attempted, skipped, or fails. If no summary was emitted, inspect the command error; configuration, Weather API collection, or batch validation failed before any report artifacts were created. Safe fix: for collection failures, fix the configuration or upstream Weather API availability and rerun the batch. For report failures, use the failed report's artifact paths from the summary, then inspect metadata, sources, module snapshot, and data package for that RunID. For a batch notification failure, inspect the notification artifact path from the top-level `notification.path`. Relevant docs: [CLI reference](cli.md), [Operations guide](operations.md). ## Batch Upload Skipped Symptom: a batch JSON summary contains `"notification":{"status":"skipped","reason":"one or more reports failed"}`. Likely cause: at least one planned report failed, so weatherreporter did not call distributor for the batch. Diagnostic: inspect the failed report items in the batch JSON summary and the matching stderr report lines. A skipped batch notification has no distributor run ID and no notification artifact path. Safe fix: fix the report-generation failure first, then rerun the batch. The batch upload is all-or-nothing. Relevant docs: [Operations guide](operations.md). ## Batch Upload Fails Symptom: every report item in a batch summary is succeeded, but the batch returns nonzero and the top-level notification has `status: "failed"`. Likely cause: the distributor upload was rejected, the distributor service was unavailable, status polling reached a terminal distributor failure, or weatherreporter rejected the batch file mapping before upload. Diagnostic: inspect `notification.error`, `notification.pipelineId`, `notification.bundleId`, `notification.idempotencyKey`, and `notification.path` in stdout. Then inspect the notification artifact; it records included report source paths, bundle paths, upload status, distributor run status, status lookup error, and raw status report JSON when available. Safe fix: fix the endpoint, token, distributor pipeline, batch identity templates, or report path templates indicated by the error, then rerun the batch. Individual report artifacts from the failed batch notification remain available and do not need to be regenerated for diagnosis. Relevant docs: [Configuration reference](config.md), [Operations guide](operations.md). ## Duplicate Batch Bundle Path Symptom: a batch returns nonzero with duplicate bundle path context before a distributor run ID is accepted. Likely cause: `notify.distributor.report_path_templates` rendered the same bundle-relative path for two included reports in the same batch. Diagnostic: inspect the error in stdout or stderr. The validation error includes the duplicate bundle path plus the report IDs, RunIDs, and managed source paths involved. Safe fix: change `notify.distributor.report_path_templates` so every report in a batch renders a unique path. Include values such as `{artifact_group}`, `{valid_start_date}`, `{batch_output_name}`, or `{run_id}` when needed. Relevant docs: [Configuration reference](config.md), [Operations guide](operations.md). ## Distributor Source Conflict Symptom: distributor accepts or rejects an upload with conflict context for a source, destination, digest, or idempotency key. Likely cause: the rendered bundle ID or idempotency key does not match the intended producer identity. A bundle ID identifies the logical source stream; an idempotency key identifies a retry of the same upload request. Diagnostic: inspect the report notification artifact linked from metadata or the batch notification artifact linked from the top-level notification path. Compare the rendered pipeline ID, bundle ID, idempotency key, included source paths, and bundle paths with `notify.distributor.*` templates and distributor pipeline state. Safe fix: keep bundle ID templates stable for the source stream that should be updated, and keep idempotency keys stable only for retries of the same generated content. Do not reuse one idempotency key for different report or batch content. Relevant docs: [Operations guide](operations.md), [Distributor adapter internals](internal/distributor-adapter.md). ## Invalid Secrets Directory Symptom: config loading fails with `read secrets directory`, `secret file`, or environment variable name context. Likely cause: `secrets.directory` points to a missing directory or contains an invalid entry. Secret entries must be regular files directly under the configured directory, and file basenames must match `[A-Za-z_][A-Za-z0-9_]*`. Diagnostic: list the configured directory and inspect entry names and file types. Do not print secret file contents. Safe fix: create the directory, remove subdirectories or symlinks, fix invalid filenames, and ensure the weatherreporter process can read each secret file. Relevant docs: [Configuration reference](config.md). ## Distributor Token Is Missing Symptom: notification fails with a message that the distributor token environment variable is not set. Likely cause: `notify.distributor.enabled` is true, but the environment variable named by `notify.distributor.token_env` was not populated directly or through `secrets.directory`. Diagnostic: check `notify.distributor.token_env`, then verify a matching secret file exists under `secrets.directory` or that the process environment includes the variable. Do not print the token value. Safe fix: create a readable secret file whose basename matches `token_env`, or set the environment variable through the service manager. Relevant docs: [Configuration reference](config.md), [Operations guide](operations.md). ## Distributor Upload Conflict Symptom: notification fails with idempotency conflict context. Likely cause: the same idempotency key was reused for different bundle content within the same distributor token and pipeline. By default the bundle ID is a stable report-stream identity and the idempotency key appends RunID. Diagnostic: inspect the failed batch JSON or stderr line for pipeline, bundle, and idempotency context. For batch commands, use the top-level notification object rather than per-report notification fields. Compare the configured templates with the report RunID or batch RunID and report path. Also inspect the notification artifact linked from metadata or from the top-level batch notification path. It records the rendered pipeline ID, bundle ID, idempotency key, upload result, distributor run status, status error, and raw run report JSON when available. Safe fix: keep idempotency templates stable for retries of the same generated report, but do not reuse the same rendered key for different generated report content. Relevant docs: [Operations guide](operations.md), [Distributor adapter internals](internal/distributor-adapter.md). ## Distributor Upload Rejected Symptom: notification fails with distributor upload rejection, HTTP status, or bundle validation context. Likely cause: the distributor endpoint rejected the token, pipeline ID, bundle ID, idempotency key, source file, or one of the rendered bundle paths. Diagnostic: inspect stdout JSON or stderr status lines for `notificationError` or the top-level batch notification `error`. Confirm `notify.distributor.endpoint`, `notify.distributor.pipeline_id_template`, `notify.distributor.report_path_templates`, and token configuration. Token values are redacted from weatherreporter errors. If the upload was accepted but destination output did not change, inspect the notification artifact's `runStatus.report`. Distributor actions such as `replace_older`, `skip_same`, `skip_destination_newer`, or `failed` explain how the destination handled the uploaded bundle. Safe fix: fix the endpoint, token, templates, or distributor-side upload configuration. The weatherreporter upload source is the managed Markdown report, not `--out` or `--out-dir` copies. Relevant docs: [Configuration reference](config.md), [Operations guide](operations.md), [Distributor adapter internals](internal/distributor-adapter.md). ## Distributor Unavailable Symptom: notification fails with network, timeout, or service unavailable context. Likely cause: the configured distributor endpoint is unreachable, slow, or temporarily unavailable. Diagnostic: check network access from the weatherreporter host to `notify.distributor.endpoint`. For batch runs, inspect the top-level notification object and the artifact linked by `notification.path`. Safe fix: restore distributor service availability and rerun the affected report or batch. Stable idempotency keys make retrying the same generated report safe unless the distributor reports a conflict. Relevant docs: [Operations guide](operations.md). ## Unknown RunID Symptom: an inspect command fails with `metadata for run id ... was not found`. Likely cause: the RunID is mistyped or the command is reading a different workspace. Diagnostic: ```sh weatherreporter inspect reports --config ./config.yml --limit 20 ``` Safe fix: copy a RunID from `inspect reports`, or use the same `--config` and workspace that generated the report. Relevant docs: [Operations guide](operations.md). ## Workspace Path Error Symptom: startup or inspection fails with workspace path validation or filesystem read/write context. Likely cause: a workspace subdirectory is absolute, escapes `workspace.root`, or the process cannot read or write the configured path. Diagnostic: review `workspace.root`, `workspace.snapshots_dir`, `workspace.reports_dir`, `workspace.data_packages_dir`, and `workspace.preflight_dir`. Safe fix: keep workspace subdirectories relative to `workspace.root`, and grant the process appropriate filesystem permissions. Relevant docs: [Configuration reference](config.md), [Operations guide](operations.md).