jackwener/OpenCLI · error · ArgumentError
shop_id must be a non-empty string
Error message
shop_id must be a non-empty string
What it means
normalizeShopId accepts either a bare shop id or a dianping shop URL (/shop/<id>) and extracts the id. This specific error is thrown when the input is empty or falsy after string coercion — e.g. null, undefined, '', or a placeholder that trims to nothing — since no id can be derived. Note that a non-empty input failing the id pattern check throws a different error ('does not look like a dianping shop id').
Source
Thrown at clis/dianping/utils.js:78
'city',
`unknown city '${cityArg}'. pass a numeric cityId or one of: ${names}`,
);
}
return id;
}
export function requireSearchLimit(value) {
const raw = value == null || value === '' ? 15 : value;
const limit = typeof raw === 'number' ? raw : Number(String(raw).trim());
if (!Number.isInteger(limit) || limit < 1 || limit > 15) {
throw new ArgumentError('limit must be an integer between 1 and 15 (dianping single page)');
}
return limit;
}
export function normalizeShopId(rawInput) {
const raw = String(rawInput || '').trim();
if (!raw) throw new ArgumentError('shop_id must be a non-empty string');
const idMatch = raw.match(/\/shop\/([^?#/]+)/);
const shopId = idMatch ? idMatch[1] : raw;
if (!/^[A-Za-z0-9_-]+$/.test(shopId)) {
throw new ArgumentError(`'${raw}' does not look like a dianping shop id`);
}
return shopId;
}
export function wrapDianpingStep(label, fn) {
return Promise.resolve()
.then(fn)
.catch((err) => {
if (err?.code) throw err;
const message = err?.message || String(err);
throw new CommandExecutionError(`dianping ${label} failed: ${message}`);
});
}View on GitHub (pinned to 49907e53dc)
Solutions
- Pass a real dianping shop id (e.g. from search results' shop_id column) or a full shop URL like https://www.dianping.com/shop/1234567.
- Verify the upstream step actually produced an id — re-run the search and confirm the shop_id field is populated before chaining.
- Guard the call: if (!shopId || !shopId.trim()) fail early with a clear message instead of invoking the command.
- Check shell/config plumbing — quoting, exported variables, and non-empty CSV/JSON fields.
Example fix
// before
const id = row.shop_id; // '' when search returned junk
await shop(id); // ArgumentError: shop_id must be a non-empty string
// after
if (!row?.shop_id?.trim()) throw new Error('upstream search returned no shop_id');
await shop(row.shop_id.trim()); Defensive patterns
Strategy: validation
Validate before calling
function hasUsableShopId(v) {
const raw = String(v ?? '').trim();
if (!raw) return false;
const m = raw.match(/\/shop\/([^?#/]+)/);
const id = m ? m[1] : raw;
return /^[A-Za-z0-9_-]+$/.test(id);
} Type guard
function isShopIdInput(v) {
return typeof v === 'string' && v.trim().length > 0;
} Try / catch
try {
const id = normalizeShopId(input);
} catch (e) {
if (e.name === 'ArgumentError' && /non-empty string/.test(e.message)) {
console.error('No shop id provided — check upstream search output / flag plumbing');
} else if (e.name === 'ArgumentError') {
console.error(`'${input}' is not a shop id or /shop/ URL`);
} else throw e;
} Prevention
- Check upstream results are non-empty before chaining shop lookups on row.shop_id.
- Pass full /shop/ URLs or bare ids; both are accepted by normalizeShopId.
- Quote and export shell variables so empty values fail loudly at your own boundary.
- Fail early in scripts: if (!shopId?.trim()) throw before invoking the command.
When it happens
Trigger: Calling the shop command with shop_id='' or whitespace only; passing an unset variable (undefined/null) from a script; piping an empty lookup result from a prior step into shop_id; a template string that interpolates to ''.
Common situations: Chained automation where a previous search returned no rows so the id variable is empty; shell variable not exported/quoted; reading an empty CSV/JSON field; forgetting to pass the --shop-id flag and an empty default being used.
Understand the failure class
Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.
Related errors
- archive search sort must be one of ${SORT_OPTIONS.join(', ')
- archive search mediatype must be one of ${MEDIATYPES.join(',
- archive search limit must be a positive integer
- archive search limit must be <= 100
- archive search query must not be empty
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/a91e858947c01e43.
Report an issue: GitHub.