jackwener/OpenCLI · error · CommandExecutionError
Substack post search failed: HTTP ${resp.status}
Error message
Substack post search failed: HTTP ${resp.status} What it means
searchPosts calls the Substack post search API (substack.com/api/v1/post/search). If the response is not ok, it throws a CommandExecutionError with the HTTP status, since the search could not complete.
Source
Thrown at clis/substack/search.js:26
}
function trim(value) {
return typeof value === 'string' ? value.replace(/\s+/g, ' ').trim() : '';
}
function publicationBaseUrl(publication) {
if (publication?.custom_domain)
return `https://${publication.custom_domain}`;
if (publication?.subdomain)
return `https://${publication.subdomain}.substack.com`;
return '';
}
async function searchPosts(keyword, limit) {
const url = new URL('https://substack.com/api/v1/post/search');
url.searchParams.set('query', keyword);
url.searchParams.set('page', '0');
url.searchParams.set('includePlatformResults', 'true');
const resp = await fetch(url, { headers: headers() });
if (!resp.ok)
throw new CommandExecutionError(`Substack post search failed: HTTP ${resp.status}`);
const data = await resp.json();
const results = Array.isArray(data?.results) ? data.results : [];
return results.slice(0, limit).map((item, index) => ({
rank: index + 1,
title: trim(item?.title),
author: trim(item?.publishedBylines?.[0]?.name),
date: trim(item?.post_date).split('T')[0] || trim(item?.post_date),
description: trim(item?.description || item?.subtitle || item?.truncated_body_text).slice(0, 150),
url: trim(item?.canonical_url),
}));
}
async function searchPublications(keyword, limit) {
const url = new URL('https://substack.com/api/v1/profile/search');
url.searchParams.set('query', keyword);
url.searchParams.set('page', '0');
const resp = await fetch(url, { headers: headers() });
if (!resp.ok)
throw new CommandExecutionError(`Substack publication search failed: HTTP ${resp.status}`);View on GitHub (pinned to 49907e53dc)
Solutions
- Check the HTTP status in the message and retry with backoff for 429/5xx
- Use an authenticated browser session so headers() carries valid cookies
- Slow down request rate and add delays between searches
- Verify the endpoint still exists if you get repeated 404s after a Substack update
Example fix
// before
const posts = await searchPosts('rust', 10); // throws on 429
// after
let posts;
try { posts = await searchPosts('rust', 10); }
catch (e) { console.warn(e.message); await sleep(5000); posts = await searchPosts('rust', 10); } Defensive patterns
Strategy: retry
Validate before calling
// ensure a browser session exists so headers() carries valid cookies
if (!session || !session.cookies) throw new Error('run within a browser session for substack search'); Type guard
null
Try / catch
try { posts = await searchPosts(q, 10); } catch (e) {
const m = /HTTP (\d+)/.exec(e.message);
if (m && ['429','502','503'].includes(m[1])) { await sleep(5000); posts = await searchPosts(q, 10); } else throw e;
} Prevention
- Add backoff on 429/5xx statuses
- Use an authenticated browser session rather than bare fetches
- Throttle search volume in loops
- Watch for Substack API changes after 404s
When it happens
Trigger: Any searchPosts call where substack.com returns a non-2xx status: rate limiting (429), auth/cookie rejection (401/403), server errors (5xx), or 404 when the endpoint changes.
Common situations: Heavy scraping triggering Substack rate limits, missing or expired browser session cookies expected by headers(), Substack API changes breaking the endpoint, datacenter IPs blocked by bot protection.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- Substack publication search failed: HTTP ${resp.status}
- HTTP ' + res.status + ' - make sure you are logged in to Ins
- NOT_FOUND
- Detached HEAD — checkout a branch first
- No 12306 stations match "${keyword}"
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/3c0563331054b6f6.
Report an issue: GitHub.