jackwener/OpenCLI · error · ArgumentError
Invalid LinkedIn Learning course URL: "${s}"
Error message
Invalid LinkedIn Learning course URL: "${s}" What it means
Thrown by parseSlug when the input is a valid http(s) URL on linkedin.com/www.linkedin.com but its pathname does not start with /learning/<segment>. The library uses that path segment as the course slug, so a LinkedIn URL without a /learning/ path cannot be resolved to a course.
Source
Thrown at clis/linkedin-learning/course.js:24
import { DOMAIN, fetchLinkedInLearningApi, normalizeWhitespace } from './shared.js';
function parseSlug(value) {
const s = normalizeWhitespace(value);
if (!s) throw new ArgumentError('<slug> is required');
let slug = s;
if (/^https?:\/\//i.test(s)) {
let parsed;
try {
parsed = new URL(s);
} catch {
throw new ArgumentError(`Invalid LinkedIn Learning URL: "${s}"`);
}
const host = parsed.hostname.toLowerCase();
if (host !== 'linkedin.com' && host !== 'www.linkedin.com') {
throw new ArgumentError(`Invalid LinkedIn Learning host: "${parsed.hostname}"`);
}
const m = parsed.pathname.match(/^\/learning\/([^/?#]+)/);
if (!m) throw new ArgumentError(`Invalid LinkedIn Learning course URL: "${s}"`);
slug = m[1];
} else {
const m = s.match(/^\/?learning\/([^/?#]+)/);
slug = m ? m[1] : s;
}
if (!/^[a-zA-Z0-9-_]+$/.test(slug)) {
throw new ArgumentError(`Invalid LinkedIn Learning slug: "${slug}"`);
}
return slug;
}
function parseCourse(el, slug) {
const title = normalizeWhitespace(el?.title);
if (!title) return null;
const description = typeof el?.description === 'string'
? el.description
: (el?.description?.text || '');
const duration = el?.duration?.unit === 'SECOND' ? String(el.duration.duration ?? '') : '';View on GitHub (pinned to 49907e53dc)
Solutions
- Pass the course slug directly instead of a URL.
- Use a URL whose path is /learning/<slug>, e.g. https://www.linkedin.com/learning/agentic-ai-basics/.
- Extract the slug from the URL you have and pass '/learning/<slug>' or just '<slug>'.
Example fix
// before opencli linkedin-learning course 'https://www.linkedin.com/posts/ai-course-123' // after opencli linkedin-learning course 'https://www.linkedin.com/learning/agentic-ai-build-your-first-agentic-ai-system/'
Defensive patterns
Strategy: validation
Validate before calling
function extractSlug(v) {
if (/^https?:\/\//i.test(v)) {
const u = new URL(v);
const m = u.pathname.match(/^\/learning\/([^/?#]+)/);
return m ? m[1] : null;
}
const m = v.match(/^\/?learning\/([^/?#]+)/);
return m ? m[1] : v;
}
// if (extractSlug(arg) === null) convert URL before calling; Type guard
function isLearningPathUrl(v) {
if (!/^https?:\/\//i.test(v)) return false;
try { return /^\/learning\/[^/?#]+/.test(new URL(v).pathname); }
catch { return false; }
} Try / catch
try {
run(['linkedin-learning', 'course', arg]);
} catch (e) {
if (String(e.message).includes('Invalid LinkedIn Learning course URL')) {
// fall back to slug-only input or a /learning/<slug> URL
} else throw e;
} Prevention
- Only pass URLs copied from /learning/ pages; post/profile/learning-path URLs are unsupported.
- Extract the slug from the address bar and pass just the slug.
- Document that the accepted URL shape is exactly https://www.linkedin.com/learning/<slug>/.
When it happens
Trigger: Calling the linkedin-learning course command with an on-domain URL such as 'https://www.linkedin.com/posts/some-post' or 'https://www.linkedin.com/learningPaths/x' (regex only matches /learning/<segment>), or a bare 'https://www.linkedin.com/'.
Common situations: Pasting a LinkedIn post, profile, or learning-path URL instead of a course URL; copying the site homepage; a domain change in LinkedIn's URL scheme (e.g. /learn/ vs /learning/) in newer product areas.
Related errors
- Invalid LinkedIn Learning host: "${parsed.hostname}"
- 1688 item expects an offer URL or offer ID
- Invalid 1688 store URL
- Invalid 1688 URL
- Expected an exact BVID or bilibili.com video URL, for exampl
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/ea489d50dc51c003.
Report an issue: GitHub.