jackwener/OpenCLI · error · CommandExecutionError
${label} returned a malformed image URL
Error message
${label} returned a malformed image URL What it means
This CommandExecutionError is thrown by parsePixivImageUrl in clis/pixiv/bookmark-download.js:36-41 when the image URL string from the Pixiv API cannot be parsed by the URL constructor. The value is a non-empty string but not a valid absolute URL (new URL(value) throws).
Source
Thrown at clis/pixiv/bookmark-download.js:40
['.gif', 'image/gif'],
['.webp', 'image/webp'],
]);
function requireExecute(value) {
if (value !== true) {
throw new ArgumentError('Refusing to write local Pixiv downloads: pass --execute');
}
}
function parsePixivImageUrl(value, label) {
if (typeof value !== 'string' || !value) {
throw new CommandExecutionError(`${label} returned a missing image URL`);
}
let url;
try {
url = new URL(value);
} catch {
throw new CommandExecutionError(`${label} returned a malformed image URL`);
}
const extension = path.extname(url.pathname).toLowerCase();
const contentType = IMAGE_CONTENT_TYPES.get(extension);
if (url.protocol !== 'https:' || url.hostname !== 'i.pximg.net' || url.username || url.password || url.port || !contentType) {
throw new CommandExecutionError(`${label} returned an untrusted Pixiv image URL`);
}
return { url: url.href, extension, contentType };
}
async function prepareIllustPlan(page, row, outputRoot) {
const pages = await pixivFetch(page, `/ajax/illust/${row.illust_id}/pages`, {
notFoundMsg: `Illustration not found: ${row.illust_id}`,
});
if (!Array.isArray(pages)) {
throw new CommandExecutionError('Pixiv pages API returned malformed payload');
}
if (pages.length === 0) {
throw new EmptyResultError('pixiv bookmark-download', `No images found for illustration ${row.illust_id}.`);View on GitHub (pinned to 49907e53dc)
Solutions
- Inspect the raw pages API payload for the illustration to see what the url field actually contains
- If the value is protocol-relative or relative, normalize it against https://i.pximg.net before parsing
- Re-authenticate or verify the illustration is accessible — restricted works can return placeholder values
- Update the CLI to handle the new Pixiv response format if the API schema changed
Defensive patterns
Strategy: type-guard
Validate before calling
function looksLikeAbsoluteUrl(value) {
if (typeof value !== 'string' || !value) return false;
try { new URL(value); return true; } catch { return false; }
}
const raw = entry.urls.original || entry.urls.regular;
if (!looksLikeAbsoluteUrl(raw)) {
console.warn('Non-absolute URL from API:', raw);
} Type guard
function isValidUrl(value) {
if (typeof value !== 'string' || !value) return false;
try { new URL(value); return true; } catch { return false; }
} Try / catch
try {
const parsed = parsePixivImageUrl(value, label);
} catch (e) {
if (e instanceof CommandExecutionError && e.message.includes('malformed image URL')) {
// Normalize protocol-relative or relative paths before retrying
const absolute = value.startsWith('//') ? 'https:' + value : new URL(value, 'https://i.pximg.net/').href;
parsed = parsePixivImageUrl(absolute, label);
} else {
throw e;
}
} Prevention
- Validate URLs from the API with new URL() before further processing
- Normalize protocol-relative ('//...') or relative paths against https://i.pximg.net upstream of the parser
- Log raw API payloads when a schema change is suspected
- Re-authenticate when payloads look degraded or contain placeholder values
When it happens
Trigger: The urls.original or urls.regular field from the /ajax/illust/<id>/pages response is a non-URL string (e.g. a relative path, placeholder text, or HTML fragment), so new URL(value) throws at clis/pixiv/bookmark-download.js:38.
Common situations: Pixiv API returning relative or protocol-relative paths after a schema change; a proxy/mirror or cached response with corrupted fields; scraping-style integrations passing non-URL strings into the parser; localized error text landing in the url field on restricted works.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- ${label} returned a missing image URL
- Pixiv bookmark item returned malformed creation date
- Pixiv item returned malformed tags payload
- Pixiv item returned malformed tag
- Pixiv bookmark item returned malformed ${label}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/c2c254bd6946936f.
Report an issue: GitHub.