jackwener/OpenCLI · warning · EmptyResultError
No Lobste.rs stories found for domain "${domain}".
Error message
No Lobste.rs stories found for domain "${domain}". What it means
This EmptyResultError is thrown by the `lobsters domain` command when the lobste.rs domain endpoint responds with HTTP 404, meaning no stories exist for the requested domain on Lobste.rs. The library treats 'no matching stories' as an expected empty result rather than a failure, so it uses EmptyResultError instead of CommandExecutionError. It lets callers distinguish 'bad input/domain has no coverage' from network or server problems.
Source
Thrown at clis/lobsters/domain.js:63
{ name: 'limit', type: 'int', default: 20, help: 'Number of stories (1-25 — single page)' },
],
columns: ['rank', 'id', 'title', 'score', 'author', 'comments', 'created_at', 'tags', 'submission_url', 'comments_url'],
func: async (args) => {
const domain = requireDomain(args.domain);
const limit = requireBoundedInt(args.limit, 20, 25);
const url = `https://lobste.rs/domains/${encodeURIComponent(domain)}.json`;
let resp;
try {
resp = await fetch(url, { headers: { 'user-agent': 'opencli-lobsters-adapter (+https://github.com/jackwener/opencli)' } });
}
catch (err) {
throw new CommandExecutionError(
`lobsters domain request failed: ${err?.message ?? err}`,
'Check that lobste.rs is reachable from this network.',
);
}
if (resp.status === 404) {
throw new EmptyResultError('lobsters domain', `No Lobste.rs stories found for domain "${domain}".`);
}
if (!resp.ok) {
throw new CommandExecutionError(`lobsters domain returned HTTP ${resp.status}`);
}
let body;
try {
body = await resp.json();
}
catch (err) {
throw new CommandExecutionError(`lobsters domain returned malformed JSON: ${err?.message ?? err}`);
}
const list = Array.isArray(body) ? body : [];
if (!list.length) {
throw new EmptyResultError('lobsters domain', `No Lobste.rs stories found for domain "${domain}".`);
}
return list.slice(0, limit).map((item, i) => ({
rank: i + 1,
id: String(item.short_id ?? ''),View on GitHub (pinned to 49907e53dc)
Solutions
- Normalize the domain before calling: strip scheme (https://), path, and trailing slash, and lowercase it (new URL(domain).hostname).
- Verify the domain actually has stories by opening https://lobste.rs/domain/<domain> in a browser.
- If the domain is valid but has no coverage, treat this as an expected empty result: catch EmptyResultError and render a friendly 'no stories' message instead of an error.
- Check the lobste.rs URL construction in clis/lobsters/domain.js if many valid domains unexpectedly 404 (possible API route change).
Example fix
// before
await cli.lobsters.domain('https://example.com/');
// throws EmptyResultError: No Lobste.rs stories found for domain
// after
const hostname = new URL('https://example.com/').hostname; // 'example.com'
await cli.lobsters.domain(hostname); Defensive patterns
Strategy: fallback
Validate before calling
function normalizeDomain(input) {
try {
const { hostname } = new URL(input.includes('://') ? input : `https://${input}`);
return hostname.toLowerCase();
} catch {
return null; // invalid input, don't call the API
}
}
const domain = normalizeDomain(userInput);
if (!domain) throw new Error(`Invalid domain: ${userInput}`); Type guard
function isValidDomain(s) {
return typeof s === 'string' && /^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)+$/i.test(s);
} Try / catch
try {
const stories = await cli.lobsters.domain(domain);
} catch (err) {
if (err.name === 'EmptyResultError') {
console.log(`No Lobste.rs stories for ${domain} — this is expected for niche domains.`);
return [];
}
throw err;
} Prevention
- Always normalize user-supplied domains with new URL(...).hostname before passing them in.
- Reject inputs containing schemes, paths, or query strings at the CLI argument-parsing layer.
- Default to a friendly 'no stories found' UX when EmptyResultError is caught.
- Sanity-check unfamiliar domains against https://lobste.rs/domain/<domain> manually once.
When it happens
Trigger: Running `lobsters domain <domain>` where GET https://lobste.rs/domain/<domain>.json returns status 404 — i.e. the domain has never had a story submitted to Lobste.rs, or the domain string is malformed so it maps to a nonexistent route.
Common situations: Typo or bad normalization of the domain (e.g. passing 'https://example.com' or 'example.com/path' instead of 'example.com'), querying an obscure internal or very new domain that no Lobste.rs user has posted, or a case/punctuation mismatch (trailing slash, uppercase).
Related errors
- Question not found
- No prices returned for train_no=${trainNo} ${fromStation.nam
- No 12306 stations match "${keyword}"
- ${label} must be a non-negative integer, got ${JSON.stringif
- limit must be a positive integer
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/edb52858326174d1.
Report an issue: GitHub.