jackwener/OpenCLI · error · ArgumentError
rubygems gem "${value}" is not a valid gem name
Error message
rubygems gem "${value}" is not a valid gem name What it means
requireGemName validates the gem name against the GEM_NAME regex /^[A-Za-z0-9][A-Za-z0-9._-]*$/ and a 100-character limit. A non-empty name that fails these checks throws ArgumentError(`rubygems gem "${value}" is not a valid gem name`) with a hint about allowed characters. This prevents sending names that can never match a real gem to rubygems.org.
Source
Thrown at clis/rubygems/utils.js:39
export function requireBoundedInt(value, defaultValue, maxValue, label = 'limit') {
const raw = value ?? defaultValue;
const n = typeof raw === 'number' ? raw : Number(raw);
if (!Number.isInteger(n) || n <= 0) {
throw new ArgumentError(`rubygems ${label} must be a positive integer`);
}
if (n > maxValue) {
throw new ArgumentError(`rubygems ${label} must be <= ${maxValue}`);
}
return n;
}
export function requireGemName(value) {
const s = String(value ?? '').trim();
if (!s) {
throw new ArgumentError('rubygems gem name is required (e.g. "rails", "sidekiq")');
}
if (s.length > 100 || !GEM_NAME.test(s)) {
throw new ArgumentError(
`rubygems gem "${value}" is not a valid gem name`,
'Use letters / digits / "._-", starting with a letter or digit (max 100 chars).',
);
}
return s;
}
export async function gemsFetch(url, label) {
let resp;
try {
resp = await fetch(url, { headers: { 'user-agent': UA, accept: 'application/json' } });
}
catch (err) {
throw new CommandExecutionError(
`${label} request failed: ${err?.message ?? err}`,
'Check that rubygems.org is reachable from this network.',
);
}View on GitHub (pinned to 49907e53dc)
Solutions
- Use the bare gem name only: `opencli rubygems info rails` (no URL, no version, no quotes).
- Strip prefixes: `basename` a URL or cut after 'gems/' before passing the value.
- Sanitize in code: `const name = raw.replace(/[^A-Za-z0-9._-]/g, '')` then re-check it is non-empty before calling.
Example fix
// before
await info({ name: 'https://rubygems.org/gems/rails' }); // throws
// after
const url = 'https://rubygems.org/gems/rails';
await info({ name: url.split('/gems/')[1] }); // 'rails' Defensive patterns
Strategy: validation
Validate before calling
const GEM_NAME = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
function validGemName(v) {
const s = String(v ?? '').trim();
return s.length > 0 && s.length <= 100 && GEM_NAME.test(s);
} Type guard
function isGemName(v) {
return typeof v === 'string' && /^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(v) && v.length <= 100;
} Try / catch
try {
await info({ name });
} catch (e) {
if (e instanceof ArgumentError && /not a valid gem name/.test(e.message)) {
console.error('Pass the bare gem name (letters/digits/._-, max 100 chars).');
} else throw e;
} Prevention
- Strip URLs and version specs down to the bare name before calling.
- Reject input with spaces, slashes, or leading punctuation early.
- Share a single gem-name validator across your scripts.
When it happens
Trigger: requireGemName receives a value that is non-empty but contains characters outside [A-Za-z0-9._-], starts with '.', '_' or '-', includes spaces, slashes, or is longer than 100 chars.
Common situations: Pasting a full gem URL ('https://rubygems.org/gems/rails') or 'gem rails' instead of the bare name; including a version spec ('rails>=7'); stray quotes or whitespace inside the token; typos like './mygem'.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- rubygems ${label} cannot be empty
- rubygems gem name is required (e.g. "rails", "sidekiq")
- --limit must be a positive integer, got ${JSON.stringify(kwa
- `endoflife ${label} must be <= ${maxValue}`
- facebook search --limit must be an integer between 1 and ${M
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/f41e23eff7002f54.
Report an issue: GitHub.