Troubleshooting¶
Start with doctor¶
rollup doctor
rollup doctor --json
rollup doctor --full
rollup doctor --network # or pass --ollama to enable Ollama checks
Fix hints are always included. Exit code 0 means no error-level checks failed (warnings are OK).
Common issues¶
Writable path inside mail root¶
Move --output-dir, --state-dir, and --log-dir outside --mail-root.
Another digest run is in progress¶
A lock is held at state/rollup.lock. Wait for the other run, or if the process
is dead, the next run recovers stale locks automatically.
Empty digest / everything skipped outside window¶
Fixture or live mail dates may be outside --lookback-days. Increase the
lookback or regenerate fixtures with python tests/generate_fixtures.py.
Ollama not reachable¶
Default digests do not need Ollama. If you passed --ollama, start the local
server or omit the flag to use preview summaries.
Provider errors vs programming faults¶
Rollup degrades only named provider transport/payload failures, such as
requests.RequestException, malformed provider JSON, or Unicode decode errors
from provider payloads. Programming faults such as TypeError or
AttributeError are not converted into fallbacks; they hard-fail so the bug is
visible.
Parse anomalies vs fatal errors¶
Kind |
Meaning |
|---|---|
Fatal parse error |
Message produced no |
Parse anomaly |
Recoverable (encoding replaced, body truncated, invalid date) |
Filter outcome |
Outside lookback window / seen undated |
Content quality |
Empty body with subject — still a valid short notification |
Missing dates use the established undated-message path; they are not fatal parse errors.
Manifests¶
Each non-dry-run digest writes state/manifests/<timestamp>-<run_id>.json
(schema version 2). Readers still accept schema 1. Failure manifests are
written whenever state_dir is writable. Inspect:
cat state/manifests/latest.json
rollup cron status
Manifests are local operational records (paths and folder names may be sensitive on shared machines). They never store message bodies, subjects, Message-IDs, prompts, model responses, or patch text.
Structured logs follow the same privacy rule: they may record status, counters, codes, and bounded exception messages, but not newsletter subject/body text, prompts, model responses, or patch contents.
Schema v2 may include final_review (apply skip reason, reject counts by code,
auto-edited prose flag) and group_summaries (ollama_calls, cache hits, stream /
cache errors, degraded).
Apply mode skipped every patch¶
Check the manifest final_review.apply_global_skip_reason and logs. Common codes:
fingerprint_missing, fingerprint_mismatch, unsafe_to_publish,
unattended_patch_cap, unattended_char_cap. Cron apply also requires
--final-review-allow-cron-apply and conservative policy.
Final-review apply binds patches to the digest fingerprint. Live model responses
may echo either echoed_digest_fingerprint or the schema alias
digest_fingerprint; cached results preserve only the model/cache echo and never
synthesise a missing echo from the host-computed fingerprint. Missing or
mismatched echoes skip the whole patch set.
Group summaries degraded / exit 2¶
Partial exit with a usable digest usually means stream failures, cache read/write errors, or all attempted group blurbs failed. Member entry summaries still render; deterministic group headers remain when a blurb is omitted.
Grouping looks wrong¶
rollup digest --grouping-report
rollup digest --no-grouping
v1 groups notification_stream, daily_editions, and sender_batch
(including an auto fallback to same-source batches). Essays and long-form
messages always stay standalone.
LinkedIn fetch failed (401 / 429 / checkpoint)¶
fromMember searches use Voyager (profileUpdatesV2) with your LinkedIn
session. Set both cookies before --linkedin or [linkedin].enabled = true.
Never store them in TOML. See CONFIG.md.
export ROLLUP_LINKEDIN_LI_AT='…' # DevTools → Cookies → li_at
export ROLLUP_LINKEDIN_JSESSIONID='ajax:…' # same pane; JSESSIONID (quotes optional)
rollup digest --linkedin
Missing
ROLLUP_LINKEDIN_LI_AT: fetch refuses to start. Dry-run warns instead of calling the network.Missing
ROLLUP_LINKEDIN_JSESSIONID:fromMembersearches need it as Voyager CSRF (csrf-token). Copy it from the same cookie pane asli_at.401 / session expired: refresh both cookies from a logged-in browser. They rotate together; a new
li_atwith a staleJSESSIONIDstill 401s.0 posts / all undated (older builds): current Rollup dates posts from activity ids and applies lookback after fetch. If
Messages parsedis 0, the session may be valid HTML-only (no Voyager) — confirm the log lineFetching LinkedIn fromMember feed (N authors) via Voyagerand that the URL hasfromMember=.429: rate limited — wait and retry. Mail-only digests may still publish as partial (exit 2).
Checkpoint / authwall: complete LinkedIn’s verification in the browser, then export fresh cookies.
Listing cache still showing old posts: LinkedIn listings and article bodies persist in
rollup.dbfor[linkedin].fetch_ttl_hours(default 24). Pass--linkedin-refresh, or setfetch_ttl_hours = 0, to force a live pull. A fetch failure may reuse a stale snapshot (linkedin_cache_stale).LinkedIn-only run (
--folder linkedin:…and no mbox): fetch failure is exit 1, not partial.Dry-run / Settings GET: never contacts LinkedIn.
Link-post still a short teaser: article fetch is on by default. Confirm
[linkedin].article_fetchis notfalseand you did not pass--no-linkedin-article-fetch. Voyager must exposeArticleComponent(content.navigationContext.actionTarget). Job posts and posts without a link card stay commentary-only. A failed article GET leaves the teaser and sets a parse warning (linkedin_article_fetch_failed,linkedin_article_empty,linkedin_article_url_invalid); it does not fail the digest.How to copy cookies: EXAMPLES.md.
Reddit fetch failed (429 / missing sub)¶
Rollup fetches public subreddit listings via a transport ladder: OAuth JSON (when env credentials are set) → public JSON → www RSS → old.reddit RSS. Unauthenticated feeds are often rate-limited (~1 request per minute per IP).
rollup digest --reddit --lookback-days 7
429 / empty body: rate limited or bot wall — wait and retry. Mail-only digests may still publish as partial (exit 2). Rollup retries 429s once per sub across the ladder, then retries failed subs once more after a longer backoff. The CLI prints a planned wait (
70sbetween subs) at fetch start and remaining time per sub; HTTP 429s add extra wait beyond that estimate.404: subreddit does not exist or name is wrong — not retried. Check
/redditor[reddit.subs.*]in TOML.Subs whose names start with
r: older builds mangled names likeraspberry_pi→aspberry_pi(badlstrip("r/")). Upgrade fixes this; if TOML has[reddit.subs.aspberry_pi], rename toraspberry_pi.Stale listing / skipped RSS: default
fetch_ttl_hours = 24reuses the last snapshot. Use--reddit-refreshor set[reddit].fetch_ttl_hours = 0.Optional OAuth (script app): set in the environment (never TOML):
ROLLUP_REDDIT_CLIENT_ID,ROLLUP_REDDIT_CLIENT_SECRET,ROLLUP_REDDIT_USERNAME,ROLLUP_REDDIT_PASSWORD. When all four are set, Rollup usesoauth.reddit.comJSON first. Same~/.config/rollup/envfile as LinkedIn cookies.Reddit-only run (
--folder reddit:feedand no mbox): fetch failure is exit 1, not partial.Dry-run / Settings GET: never contacts Reddit.