{"record":{"id":"187812e38e074304","repo":"jackwener/OpenCLI","slug":"instagram-media-metadata-returned-an-invalid-downl","errorCode":null,"errorMessage":"Instagram media metadata returned an invalid download URL for item #${index + 1}","messagePattern":"Instagram media metadata returned an invalid download URL for item #(.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/instagram/download.js","lineNumber":98,"sourceCode":"        kind: kind,\n        shortcode,\n        canonicalUrl: `https://www.instagram.com/${kind}/${shortcode}/`,\n    };\n}\nexport function buildInstagramDownloadItems(shortcode, items) {\n    if (!Array.isArray(items)) {\n        throw new CommandExecutionError('Instagram media metadata returned a malformed media list');\n    }\n    return items.map((item, index) => {\n        if (!item || typeof item !== 'object' || !['image', 'video'].includes(item.type)) {\n            throw new CommandExecutionError(`Instagram media metadata returned malformed media item #${index + 1}`);\n        }\n        let downloadUrl;\n        try {\n            downloadUrl = new URL(String(item.url || ''));\n        }\n        catch {\n            throw new CommandExecutionError(`Instagram media metadata returned an invalid download URL for item #${index + 1}`);\n        }\n        if (!['http:', 'https:'].includes(downloadUrl.protocol)) {\n            throw new CommandExecutionError(`Instagram media metadata returned an unsupported download URL for item #${index + 1}`);\n        }\n        const fallbackExt = item.type === 'video' ? '.mp4' : '.jpg';\n        let ext = fallbackExt;\n        const candidateExt = path.extname(downloadUrl.pathname).toLowerCase();\n        if (candidateExt && candidateExt.length <= 8)\n            ext = candidateExt;\n        return {\n            type: item.type,\n            url: downloadUrl.toString(),\n            filename: `${shortcode}_${String(index + 1).padStart(2, '0')}${ext}`,\n        };\n    });\n}\nexport function buildInstagramFetchScript(shortcode) {\n    // The persisted GraphQL query this used to send now answers HTTP 200 with","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/instagram/download.js#L80-L116","documentation":"Thrown by buildInstagramDownloadItems when item.url for a media entry cannot be parsed by new URL(String(item.url || '')). The metadata item exists and has a valid type, but its download URL is missing or unparseable.","triggerScenarios":"A media item whose url field is empty, null, or a relative/garbage string that new URL() rejects — often from an incomplete or degraded metadata fetch inside the browser page.","commonSituations":"Instagram serving partial CDN data when logged out or rate-limited; items where the video/image rendition URL failed to build in the page script; API shape changes removing the url field.","solutions":["Re-run the command with a valid (logged-in if needed) browser session","Retry later if Instagram is rate-limiting or returning degraded data","Update the library if Instagram changed where the CDN URL lives in the metadata"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"for (const item of items) {\n  let u; try { u = new URL(String(item.url || '')); } catch { throw new Error('Item has no parseable download URL; refetch metadata'); }\n}","typeGuard":"function hasDownloadUrl(item) {\n  if (!item || typeof item.url !== 'string') return false;\n  try { new URL(item.url); return true; } catch { return false; }\n}","tryCatchPattern":"try {\n  await igDownload(url);\n} catch (e) {\n  if (/invalid download URL/.test(e.message)) {\n    console.error('A media item lacked a usable URL; retry with a fresh session.');\n  } else throw e;\n}","preventionTips":["Retry metadata fetches that return partial data","Keep sessions logged in so CDN URLs are fully populated","Update the library if the metadata url field location changed"],"tags":["browser-automation","url-parsing","instagram-api"],"backgroundTag":"malformed-response-payload","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}