jackwener/OpenCLI · error · Error
relay_unavailable
relay_unavailable
Error message
[taxonomy=relay_unavailable] site=${site} command=detail missing required detail url What it means
runProcurementDetail requires a target URL to open a detail page. If the url argument is empty or whitespace-only after cleanText, it throws a taxonomy error with code 'relay_unavailable' and detail 'missing required detail url' — the relay/data source gave nothing to fetch.
Source
Thrown at clis/jianyu/shared/procurement-detail.js:50
const bodyText = clean(document.body ? document.body.innerText : '');
const maxLength = 12000;
const limitedText = bodyText.length > maxLength ? bodyText.slice(0, maxLength) : bodyText;
const dateMatch = limitedText.match(/(20\\d{2})[.\\-/年](\\d{1,2})[.\\-/月](\\d{1,2})/);
const publishTime = dateMatch
? dateMatch[1] + '-' + String(dateMatch[2]).padStart(2, '0') + '-' + String(dateMatch[3]).padStart(2, '0')
: '';
return {
title,
detailText: limitedText,
publishTime,
};
})()
`);
}
export async function runProcurementDetail(page, { url, site, query = '', }) {
const targetUrl = cleanText(url);
if (!targetUrl) {
throw taxonomyError('relay_unavailable', {
site,
command: 'detail',
detail: 'missing required detail url',
});
}
let lastError = null;
for (let attempt = 1; attempt <= DETAIL_MAX_ATTEMPTS; attempt += 1) {
try {
const payload = await extractDetailPayload(page, targetUrl);
if (!payload || typeof payload !== 'object') {
throw taxonomyError('extraction_drift', {
site,
command: 'detail',
detail: `detail extraction returned invalid payload: ${targetUrl}`,
});
}
const row = payload;
const title = cleanText(row.title);View on GitHub (pinned to 49907e53dc)
Solutions
- Pass a non-empty url to the detail command
- Check the upstream search row actually contains a detail link before calling detail
- Fix the list-page parser if the URL field is being dropped
- Add a pre-call check that skips/flags rows without URLs
Example fix
// before
await runProcurementDetail(page, { site: 'jianyu', url: row.link });
// after
if (row.link && row.link.trim()) {
await runProcurementDetail(page, { site: 'jianyu', url: row.link });
} else {
console.warn('skip row without detail url', row.id);
} Defensive patterns
Strategy: validation
Validate before calling
if (!url || !String(url).trim()) {
throw new Error('refusing to call detail without a url');
} Type guard
function hasDetailUrl(row) {
return typeof row?.link === 'string' && row.link.trim().length > 0;
} Try / catch
try {
await runProcurementDetail(page, { site, url });
} catch (e) {
if (/\[taxonomy=relay_unavailable\]/.test(e.message)) {
console.warn('skipping row: no detail url');
return null;
}
throw e;
} Prevention
- Filter upstream search rows without links before batch detail runs
- Validate CLI arguments before invoking detail
- Track how often rows lack URLs — it signals list-page parser drift
- Default to skipping rather than failing whole batches
When it happens
Trigger: Calling the procurement 'detail' command with url undefined, empty string, or a value that normalizes to empty (e.g. an upstream search row missing its link field).
Common situations: Downstream code passing a row whose URL field was not extracted (parsing drift), shell/CLI invocations omitting the --url argument, upstream list API returning items without detail links.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- ${label} did not include a stable numeric id.
- ${label} did not include a stable text value.
- symbol is required
- boss ${name} cannot be empty
- <username> is required
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/151024244e54c598.
Report an issue: GitHub.