From 6b1ff862f36126a7be5eb09dce7f0dfee283c946 Mon Sep 17 00:00:00 2001 From: Eric Rakestraw Date: Fri, 31 Jul 2026 01:03:58 +0000 Subject: [PATCH] Refresh troubleshooting guidance --- docs/troubleshooting.md | 645 ++++++++++++++-------------------------- 1 file changed, 216 insertions(+), 429 deletions(-) diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index e9c0aae..02b7104 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -1,484 +1,271 @@ -# Weatherreporter Troubleshooting +# 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. +Use the error from the command together with the run artifacts when a run ID is +available. Start with [`inspect metadata`](cli.md#inspection-commands) to identify the +report and artifact paths, then use the narrower inspection command named +below. Do not remove a workspace to diagnose a failure: it contains the +evidence needed to correct it safely. -## `weather_api.base_url is required` +## A command or configuration is rejected before work starts -Symptom: a generation command fails before collecting weather data. +Symptom: The command exits before it creates a run, with an unknown-flag, +missing-argument, invalid date or time bound, invalid timezone, or +`weather_api.base_url` message. -Likely cause: no Weather API base URL is configured. +Likely cause: The command does not accept that option for the requested report, +or required command and configuration values are absent or malformed. -Diagnostic: +Diagnostic: Compare the command with [`generate` and `run`](cli.md#commands-and-usage) +and review the configured value named in the error. `generate daily` requires +`--date`; `generate storm` requires both `--start` and `--end`. -```sh -weatherreporter generate daily --config ./config.yml --date 2026-05-29 -``` +Safe fix: Correct only the reported option or configuration value. Use an +absolute Weather API URL and a valid IANA timezone; do not change unrelated +workspace data. -Safe fix: add `weather_api.base_url` to the config file, or pass the intended -config path with `--config`. +See also: [Configuration](config.md) and [Weather API integration](integrations/weatherapi.md). -Relevant docs: [Configuration reference](config.md). +## Weather data cannot be collected -## `weather_api.base_url must be an absolute URL` +Symptom: A generation command fails while fetching weather data, or reports +`hourly forecast data is missing` or `contains no periods`. -Symptom: config loading fails with a base URL validation error. +Likely cause: The Weather API is unavailable, its configured endpoint or +credentials are unsuitable, or the response lacks the hourly forecast required +by the selected report. -Likely cause: `weather_api.base_url` is missing a scheme or host. +Diagnostic: Check the service status and the configured base URL, then retry +the same report. If a run ID was produced, run `weatherreporter inspect sources +RUN_ID` to see the recorded source result. -Diagnostic: inspect the configured value in the file passed to `--config`. +Safe fix: Restore access to the configured Weather API or choose a reporting +period supported by the returned forecast. Do not invent missing hourly values +in local artifacts. -Safe fix: use an absolute URL such as `https://weather.api.example.com/`. +See also: [Configuration](config.md) and [Weather API integration](integrations/weatherapi.md). -Relevant docs: [Configuration reference](config.md). +## Optional source warnings appear -## Invalid Timezone +Symptom: The report succeeds but its output says that a source supplied a +warning or degraded result. -Symptom: config loading fails with `weather_api.timezone` context, or a CLI -timezone override fails. +Likely cause: An optional source did not return usable data; mandatory weather +collection still completed. -Likely cause: `weather_api.timezone` or `--tz` is not recognized. +Diagnostic: Run `weatherreporter inspect sources RUN_ID` and identify the +source and warning recorded for that run. -Diagnostic: +Safe fix: Correct the affected source configuration or service issue, then +generate a new report if the missing optional information is needed. Keep the +existing run for comparison. -```sh -weatherreporter generate daily --tz America/Chicago --date 2026-05-29 -``` +See also: [Inspecting a run](cli.md#inspection-commands) and [Operations](operations.md). -Safe fix: use an accepted timezone value, such as an IANA timezone name, -`Chicago`, `Stl`, a US timezone abbreviation, or a UTC offset. +## Scriptorium cannot be prepared -Relevant docs: [Configuration reference](config.md). +Symptom: The report fails with a fragment such as `run scriptorium render`, or +the Scriptorium executable cannot be started. -## Storm Command Rejects Time Bounds +Likely cause: The configured executable, profile, prompt, or its local runtime +environment is unavailable to Weatherreporter. -Symptom: `generate storm` fails with `requires --start`, `requires --end`, or -`requires --end after --start`. +Diagnostic: Confirm that the configured executable can be run by the same user +and inspect `weatherreporter inspect metadata RUN_ID` when a run ID is shown. -Likely cause: the manual event window is missing or invalid. +Safe fix: Repair the executable path or the Scriptorium configuration and retry +the report. Do not edit generated artifacts to bypass preparation. -Diagnostic: +See also: [Configuration](config.md) and [Operations](operations.md). -```sh -weatherreporter generate storm --start 2026-05-29T18:00 --end 2026-05-30T06:00 -``` +## Scriptorium preflight fails -Safe fix: provide both bounds. Use `YYYY-MM-DDTHH:MM` in the configured -timezone, or RFC3339 timestamps with explicit offsets. +Symptom: A Scriptorium-backed report stops before text generation, often with +a `scriptorium render exited with code` fragment. -Relevant docs: [CLI reference](cli.md). +Likely cause: Scriptorium rejected the render request, prompt, profile, or data +package before it could run the report. -## Weather API Fetch Fails +Diagnostic: Inspect the run metadata and the saved preflight artifact path it +references. Compare the reported Scriptorium diagnostic with its configuration. -Symptom: generation fails with `fetch /...`, an HTTP status, or request context. +Safe fix: Correct the reported Scriptorium input or configuration, then create +a new run. Preserve the failed preflight artifact for support or comparison. -Likely cause: the configured Weather API endpoint is unreachable, returned a -non-2xx response after retries, or returned an invalid response envelope. +See also: [Inspecting a run](cli.md#inspection-commands) and [Operations](operations.md). -Diagnostic: +## Scriptorium report execution fails -```sh -weatherreporter generate daily --config ./config.yml --date 2026-05-29 -``` +Symptom: Preparation succeeded, but generation stops with a +`scriptorium run exited with code` fragment. -Safe fix: verify `weather_api.base_url`, network access, and the Weather API -service response. The adapter first warms up `/conditions/current`, then fetches -`/observations`, `/conditions/current`, `/forecast/hourly`, -`/forecast/narrative`, `/alerts/active`, `/discussion`, -`/weatherstories/latest`, and `/outlooks/convective`. Transient VPN wake-up -failures and retryable upstream statuses are retried automatically. +Likely cause: The Scriptorium run failed after preflight, for example because +its prompt execution or runtime dependency failed. -Relevant docs: [Configuration reference](config.md). +Diagnostic: Inspect the run metadata and preflight artifact, then review the +exit diagnostic from the command. This distinguishes a run failure from a +preflight failure. -## Hourly Forecast Is Missing +Safe fix: Correct the Scriptorium issue identified by that diagnostic and run +the report again; leave the failed run artifacts in place. -Symptom: generation fails with hourly forecast context, such as missing hourly -data or an hourly forecast containing no periods. +See also: [Operations](operations.md). -Likely cause: hourly forecast data is required for generated reports. +## Generated text fails validation -Diagnostic: check the Weather API response for `/forecast/hourly`. +Symptom: A generated-text report fails after Scriptorium returns text, with a +message about generated text or required report content. -Safe fix: restore hourly forecast data at the Weather API. Missing-source -policy cannot make hourly optional. +Likely cause: Returned text does not meet the report's validation rules. -Relevant docs: [Configuration reference](config.md), [Operations guide](operations.md). +Diagnostic: Use `weatherreporter inspect metadata RUN_ID` to find the saved raw +generated-text artifact, and inspect it alongside the reported validation +message. -## Source Warnings Appear +Safe fix: Correct the upstream prompt or generation configuration that caused +the invalid output, then create a new run. Do not hand-edit saved raw text and +present it as a validated report. -Symptom: generation succeeds, but metadata or `inspect sources` shows source -warnings. +See also: [Operations](operations.md). -Likely cause: an optional source was missing or malformed under a warning -missing-source policy. +## Report template rendering fails -Diagnostic: +Symptom: Scriptorium output is available, but the report fails while building +the final Markdown document. -```sh -weatherreporter inspect sources RUN_ID -weatherreporter inspect metadata RUN_ID -``` +Likely cause: The selected report template or the render context is +incompatible with the generated or collected data. -Safe fix: inspect the warning `source`, `code`, `message`, and `endpoint`. Fix -the upstream optional source, or intentionally change the relevant -`missing_source` policy. +Diagnostic: Inspect the metadata, generated-text result, and render-context +artifacts for the run. Note the template or missing-field fragment in the +error rather than relying on a complete error string. -Relevant docs: [Configuration reference](config.md), [Operations guide](operations.md). +Safe fix: Correct the template or its supported inputs in source control, test +the change, and create a new report. Do not alter the saved context merely to +make one historical run render. -## `scriptorium` Is Not Found Or Cannot Start +See also: [Operations](operations.md). -Symptom: generation fails with `run scriptorium render` or `run scriptorium` -and an executable or OS error. +## A report fails after artifacts are saved -Likely cause: the configured Scriptorium binary is unavailable or not -executable. +Symptom: A generation command reports an error after showing a run ID, such as +an error writing the managed report, copying `--out`, saving metadata, or +notifying Distributor. -Diagnostic: check `scriptorium.binary` in config and run the same binary outside -`weatherreporter`. +Likely cause: A local filesystem permission or path problem, an unavailable +destination for `--out`, or a later report-delivery failure occurred after +earlier steps succeeded. -Safe fix: install Scriptorium, update `scriptorium.binary`, or fix executable +Diagnostic: Run `weatherreporter inspect metadata RUN_ID` and check the exact +path and operation named in the error. For an `--out` failure, verify only the +specified destination directory and filename. + +Safe fix: Repair access to that exact path or disable the optional delivery +step only when appropriate, then generate a new report. Keep the existing +managed artifacts untouched. + +See also: [Operations](operations.md) and [Distributor integration](integrations/distributor/pkg-upload.md). + +## A batch has partial report failures + +Symptom: `run morning` or `run evening` returns nonzero and reports both +succeeded and failed report items. + +Likely cause: A report-level collection, generation, rendering, or local +output failure affected one or more planned reports; the remaining reports +continue independently. + +Diagnostic: Read the per-report status lines, then inspect the run ID for each +failed item with `weatherreporter inspect metadata RUN_ID`. + +Safe fix: Correct the specific failure and rerun the batch or affected report. +Do not delete successful reports simply because another item failed. + +See also: [Batch commands](cli.md#commands-and-usage) and [Operations](operations.md). + +## A batch upload is skipped + +Symptom: The batch result says Distributor notification was skipped because +one or more reports failed. + +Likely cause: Batch notification intentionally runs only after every planned +report succeeds. + +Diagnostic: Review the failed report items and their metadata; a skipped batch +notification is expected while any item is failed. + +Safe fix: Resolve the report failures and rerun the batch. Do not upload a +partial bundle by manually reusing batch artifacts. + +See also: [Batch commands](cli.md#commands-and-usage) and [Operations](operations.md). + +## Distributor notification fails + +Symptom: A completed report or otherwise successful batch reports a Distributor +error, including a rejected upload, source or idempotency conflict, or service +unavailability. + +Likely cause: Distributor rejected the request identity or bundle, required +credentials are unavailable, or the remote service cannot be reached. + +Diagnostic: Inspect the report metadata or batch result for the notification +artifact and the error fragment. Verify the configured Distributor endpoint and +request identity without exposing credentials. + +Safe fix: Resolve the reported remote conflict, configuration, or availability +issue and create a new report or rerun the batch. Do not modify recorded bundle +or idempotency artifacts to force an upload. + +See also: [Configuration](config.md), [Distributor integration](integrations/distributor/pkg-upload.md), and [Operations](operations.md). + +## Secrets cannot be loaded + +Symptom: Startup reports `read secrets directory`, `secret file`, or a token +environment-variable error before the affected service can be used. + +Likely cause: The configured secrets directory cannot be read, contains a +non-regular file, or does not supply the environment variable required by an +enabled integration. + +Diagnostic: Check the configured secrets directory path, ownership, and that +each intended secret is a regular file. Confirm the variable name from +configuration only; never print or paste its value. + +Safe fix: Correct permissions, file type, or the missing secret file, then +retry. Keep secret values out of commands, logs, tickets, and artifacts. + +See also: [Configuration](config.md) and [Operations](operations.md). + +## A run ID or saved state cannot be found + +Symptom: An inspection command reports that metadata for a run ID was not +found, or a report cannot use a prior snapshot. + +Likely cause: The run ID is wrong, the configured workspace is different from +the one that created the run, or no compatible prior snapshot exists. + +Diagnostic: Use `weatherreporter inspect reports` to list available reports in +the current workspace, then copy the run ID from that output. Confirm the +workspace configuration before retrying a prior-snapshot operation. + +Safe fix: Use an existing run ID and its original workspace, or generate a new +compatible report when no prior snapshot is available. Do not fabricate state +files or run IDs. + +See also: [Inspecting a run](cli.md#inspection-commands) and [Operations](operations.md). + +## Workspace paths cannot be read or written + +Symptom: Startup or report persistence reports a workspace-path, permission, +or "must be relative to workspace root" error. + +Likely cause: A configured artifact directory escapes the workspace, or the +current user lacks access to the specific workspace location. + +Diagnostic: Check the named configuration path against the configured workspace +root and inspect ownership and permissions of that exact directory. + +Safe fix: Set the path to a location within the workspace or repair access to +the named directory, then rerun. Do not remove the workspace or broadly relax 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: report-specific distributor 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: configure a per-report distributor path override 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`, -report-specific distributor paths, 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). +See also: [Configuration](config.md) and [Operations](operations.md).