#sbot Archival Quality Improvements (2026-05)
This document captures concrete problems found during the 2026 grok_test collection
and minimal, suckless-style fixes.
#The 4 Problems Identified
#1. Old Web Mirrors Are Painful (Dead HTTPS + Slow Hosts)
Evidence from tests:
- oocities-org: Flood of "SSL peer certificate or SSH remote key was not OK" on almost every subpage.
- textfiles-com: Repeated timeouts on robots.txt and root, exhausted 3 retries and gave up.
Root causes in current code:
- fetch.c: strict
CURLOPT_SSL_VERIFYPEER=1 and VERIFYHOST=2 with no option to relax for archival use.
- fetch.h: Hardcoded
FETCH_MAX_RETRIES=3 and short exponential backoff (base 2s).
- No concept of "known slow host" or per-host backoff.
- No way to treat certain certificate errors as non-fatal for old archives.
Proposed minimal changes:
- Add
IGNORE_SSL_ERRORS compile-time option in config.h (default 0 for safety).
- Increase default retries or make
FETCH_MAX_RETRIES and backoff tunable in config.h.
- Consider a small "known bad hosts" mechanism or at least better logging.
#2. Pathological Bloat Risk
Evidence:
- lowendmac-com ballooned to 250MB with only 5 files because early pages inlined enormous images.
Root causes:
MAX_FILE_SIZE (50MB) is defined in config.h but never enforced during fetch or inlining.
- No per-resource size cap is passed to libcurl (
CURLOPT_MAXFILESIZE is not used).
- No early rejection of giant resources before base64 inlining (which multiplies memory).
Proposed minimal changes:
- Actually wire
MAX_FILE_SIZE into fetch.c (use CURLOPT_MAXFILESIZE + check after download).
- Skip inlining resources over a certain size (new config option or reuse MAX_FILE_SIZE).
- Add a warning when a resource is skipped due to size.
#3. Timeout Fragility on Slow Sites
Evidence:
- Multiple runs (including stretch targets) were killed by the 3-minute external tool timeout before sbot could finish.
- textfiles and oocities both showed repeated "Timeout was reached".
Root causes:
- REQUEST_TIMEOUT is 60s (reasonable).
- But there is no progressive backoff for hosts that are consistently slow.
- No "slow host" tracking that increases timeouts or reduces parallelism for that host.
- The global rate limit (RATE_LIMIT_MS) is the only politeness mechanism.
Proposed minimal changes:
- Make REQUEST_TIMEOUT and CONNECT_TIMEOUT configurable in config.h (they already are, but document better).
- Add optional "slow host" backoff (simple host hash + failure counter).
- Consider a compile-time
ARCHIVAL_MODE that is more patient.
#4. Asset Writing Failures on Messy Filenames / Long Paths
Evidence:
- vintage-computer-com had many "cannot write asset" warnings for paths like
2020test/images/chmopenhouse/... with long or special names.
Root causes:
url_to_path() does basic query/hash stripping and extension logic, but does almost no sanitization of the actual path components.
- No truncation of overly long filenames.
- No replacement of characters that are problematic on some filesystems.
sanitize_filename() exists but is only used for the top-level output directory name.
Proposed minimal changes:
- Improve
url_to_path() (or add a helper) to sanitize individual path segments:
- Remove or replace dangerous characters (
/ \ : * ? " < > |).
- Truncate overly long segments.
- Optionally percent-decode for nicer on-disk names (optional, behind define).
- Make the sanitization behavior controllable via config.h for "strict archival" vs "nice filenames".
#Design Principles for Fixes
- All changes must be compile-time (config.h) where possible — suckless style.
- No new dependencies.
- Keep the binary small and the code auditable.
- Prefer failing safely / warning over crashing or producing garbage archives.
- Improve robustness for the "primary archival" use case the user wants, without weakening safety for normal use.
#Implementation Order (Minimal Impact First)
- Wire up
MAX_FILE_SIZE enforcement (biggest bloat win).
- Add
IGNORE_SSL_ERRORS option (biggest old-web quality of life win).
- Improve filename sanitization in url_to_path.
- Make retry / timeout values more configurable + add simple slow-host backoff.
- Update documentation and defaults if needed.
#Implemented Changes (2026-05)
All changes follow suckless principles: compile-time configuration, minimal diff, no new dependencies.
#1. MAX_FILE_SIZE Enforcement (anti-bloat)
- Wired
CURLOPT_MAXFILESIZE into libcurl.
- Added post-download size check in fetch_url.
- Added guard in fetch_and_encode before base64 inlining.
- This directly addresses the lowendmac 250MB bloat case.
#2. IGNORE_SSL_ERRORS Option (old web support)
- New define in config.h (default 0 = strict).
- When set to 1, relaxes SSL peer/host verification.
- This makes archiving old Geocities-style mirrors and dead personal sites practical without constant warnings or early failure.
#3. Improved Filename Sanitization
- Added character sanitization in url_to_path (replaces \ : * ? " < > | with _).
- Helps with the long/weird paths seen in vintage-computer dumps.
#4. Better Defaults for Archival Use
- Increased
FETCH_MAX_RETRIES from 3 → 5.
- Increased default
REQUEST_TIMEOUT from 60s → 90s.
- These give more resilience on slow historical hosts without changing behavior drastically for normal use.
These changes make sbot significantly more robust as a primary archival tool while keeping the codebase small and the philosophy intact.