A post-mortem on five categories of bugs encountered while deploying content to Arweave, configuring a Cloudflare Worker, maintaining RSS feeds, and publishing long-form articles to Nostr. Each problem is recorded with enough detail to reproduce and fix it.
1. ARNS Update Racing CDN Propagation
The Arweave Name System (ARNS) maps a human-readable name (e.g., archerships) to a manifest transaction ID. A deploy script that calls updateArns() immediately after uploading the manifest will race the CDN: CDN77 (the caching layer behind arweave.net) may not have seeded the manifest data yet. The result is a site-wide 404 -- the ARNS record points to a valid txId, but every path returns 404 because the CDN hasn't received the manifest bundle.
Fix: add a waitForManifest() polling loop that retries https://arweave.net/raw/{txId} every 30 seconds (up to 15 attempts) before calling updateArns(). Bundles under 1 MB typically propagate within 3-5 minutes. Bundles over 3 MB can take 7-10 minutes.
2. ar.io Gateway Stale ANT Cache
Even after the ARNS record is correctly updated, the ar.io gateway node behind NAME.arweave.net caches the ANT state internally. Because AO (the decentralized compute layer that processes ANT transactions) deduplicates identical messages, re-sending the same ARNS update has no effect if the message is byte-for-byte identical to the last one.
Symptom: archerships.arweave.net serves 404. CDN77 caches the 404. But arweave.net/raw/{txId} returns 200. The ARNS record is correct; the gateway just hasn't picked it up.
Fix: submit a second ARNS update with a different ttlSeconds value (e.g., 600 instead of 300). This generates a distinct AO message, bypassing deduplication and forcing the gateway to re-read the ANT state. Once the gateway flips, restore the TTL to 300.
3. ARNS TTL: 3600s Means One-Hour Outages
The ARNS record includes a ttlSeconds field that tells caching layers how long to hold the resolved manifest txId. At the original default of 3600s, the stale CDN cache caused by the race condition in problem 1 produced a one-hour site outage.
Fix: lower ttlSeconds to 300. Any future stale-cache event recovers within 5 minutes rather than an hour. The cost is slightly more frequent gateway lookups, which is negligible for a low-traffic static site.
4. Cloudflare Worker CSP Overriding Page-Level CSP
A Cloudflare Worker sitting in front of the ar.io gateway sets HTTP response headers, including Content-Security-Policy. Response headers always take precedence over <meta http-equiv="Content-Security-Policy"> tags in the page. The Worker's CSP was missing two directives:
'wasm-unsafe-eval'-- required by pagefind's WebAssembly engine'unsafe-inline'-- required by the inline theme-toggle script
Without 'wasm-unsafe-eval', pagefind returned 0 results: the WebAssembly module was blocked before it could execute. Without 'unsafe-inline', the theme toggle silently failed in strict mode.
Fix: update the Worker script to include both directives in script-src.
Takeaway: when debugging a CSP violation on a Cloudflare-proxied site, check response headers first, not the page source. The Worker's header wins every time.
5. RSS Feeds: Two Compounding Bugs
The RSS feeds at archerships.com/feeds/ had not been regenerated since April despite four essays published after that date.
Bug 1 -- missing pipeline step: gen-feeds.py existed but was never called in build.sh. Fix: add python3 scripts/gen-feeds.py to the build sequence.
Bug 2 -- wrong filename stem: gen-feeds.py used the source .md file's stem to derive the built HTML filename. For directory-based essays (stored as SLUG/SLUG-source-v1-DATE.md), the stem is SLUG-source-v1-2026-05-28, which never matches the actual HTML file SLUG.html. Of 149 essays, 147 were in this format and were silently dropped. The feeds showed 2 essays.
Fix is one line: when the .md is inside a subdirectory, use the parent directory name as the slug.
if md.parent != CONTENT_DIR and md_name != 'frontmatter':
md_name = md.parent.name
Lesson: silent data loss is the worst kind. The feed appeared valid (it had items, it validated as RSS) but was missing 98% of its content. A post-build assertion on item count would have caught this immediately.
6. Nostr Publishing: Three Problems
pynostr RelayManager hangs. RelayManager.open_connections() blocks on relay websocket connections with no timeout parameter. If relays are slow or unresponsive the script hangs indefinitely. An initial workaround (wrapping in a thread with join(timeout)) was fragile. The real fix was to replace the entire publisher with a wrapper around nak -- the reference Nostr CLI by fiatjaf. nak handles connections, signing, and confirmation natively. The private key is loaded from the system keychain and passed via NOSTR_SECRET_KEY environment variable, never as a command argument.
Missing cover image. Nostr kind-30023 articles display a cover image via the image tag, which must be an HTTPS URL. The adapted cover image existed locally but was never uploaded to a public host, so the tag was omitted entirely. Fix: auto-upload the adapted image to Arweave via the Turbo bundler and pass the resulting permanent URL as the image tag.
Missing summary tag. Clients like Yakihonne and Habla.news display the summary tag as a description in article listings. It was never set. Fix: extract the first paragraph from the built essay HTML and pass it to nak as --tag summary=....
Want to stay in touch?
- Signal (announcements): https://signal.group/#CjQKIGLn7xDB0uOXMMlbKlsKEG0CmkmL9gk3U0SeIX0KlKRZEhDoqIluCXo84TrBz-2tMJD7
- Signal (discussion): https://signal.group/#CjQKIDA0v6tUciWe-3jRArkbYttju8xfuoczTOfMrGuvhmEZEhCrOnPk-IWFmFmipdI1EHxv
- Signal: archerships.43 (https://signal.me/#eu/9JUc8x9c-QA0_-QR9qQd0HUmjsnAG1BeOJM2nDo5DopjIPq5bThAJYr99lsh0cPP)
- Mailing list: https://archerships.substack.com/subscribe
- Email: [email protected]
- Website: https://archerships.com
- Substack: https://substack.com/@archerships
- Twitter: https://x.com/archerships
- Facebook: https://www.facebook.com/archerships
- Yahihonne: https://yakihonne.com/profile/nprofile1qqsgr0xn6vvr8su9ptzj4n50j8vzmczzayed0wcl5rdnvh0tc6xhqncy6jrjw
- Nostr-npub:
npub1sx7d85ccx0pc2zk99t8glywc9hsy96fj67a3lgxmxew7h35dwp8shak49e - Odysee: https://odysee.com/@archerships:6
- TikTok: https://www.tiktok.com/@archertships
Support my work
- Donations (crypto): https://trocador.app/anonpay/?ticker_to=xmr&network_to=Mainnet&address=85e4n5bgLTWiAWZbkjbbF5MLrwyiU8kjxHWHL9t6vDE5MyNUCPzBuZUNDcvbCisC5iW5PPBP9ETRQUWQQjMuvAhHRFaYCeM&donation=True&simple_mode=True&name=Archerships&[email protected]&ticker_from=xmr&network_from=Mainnet&bgcolor=000000ff
- Donations (fiat): https://ko-fi.com/archerships
- Consulting: privacy / crypto / censorship consulting – email or Signal