jackwener/OpenCLI · warning · ArgumentError

weread-official: scope must be one of: ${Object.keys(SEARCH_

Error message

weread-official: scope must be one of: ${Object.keys(SEARCH_SCOPES).join(', ')}

What it means

Thrown by `weread-official search` when the `scope` argument is not a key of SEARCH_SCOPES (validated with hasOwnProperty after trimming). The scope selects which book catalog the WeRead search API queries (default 'ebook'). Like the type check, this is a case-sensitive enum validation before any request is made.

Source

Thrown at clis/weread-official/search.js:60

    site: 'weread-official',
    name: 'search',
    access: 'read',
    description: 'Search WeRead store via the official agent gateway',
    domain: 'weread.qq.com',
    strategy: Strategy.PUBLIC,
    browser: false,
    args: [
        { name: 'keyword', positional: true, required: true, help: 'Search keyword' },
        { name: 'scope', default: 'ebook', choices: Object.keys(SEARCH_SCOPES), help: 'Search type (all/ebook/webnovel/audio/author/fulltext/booklist/mp/article)' },
        { name: 'count', type: 'int', help: 'Page size (gateway default 15 when omitted)' },
        { name: 'max-idx', type: 'int', default: 0, help: 'Pagination offset, use searchIdx of last item from previous page' },
    ],
    columns: ['rank', 'scope', 'bookId', 'title', 'author', 'rating', 'readingCount', 'category', 'searchIdx', 'cover', 'intro', 'link'],
    func: async (args) => {
        const keyword = requireText(args.keyword, 'keyword');
        const scopeKey = String(args.scope ?? 'ebook').trim();
        if (!Object.prototype.hasOwnProperty.call(SEARCH_SCOPES, scopeKey)) {
            throw new ArgumentError(
                `weread-official: scope must be one of: ${Object.keys(SEARCH_SCOPES).join(', ')}`,
            );
        }
        const scope = SEARCH_SCOPES[scopeKey];
        const params = { keyword, scope, maxIdx: args['max-idx'] ?? 0 };
        if (args.count !== undefined && args.count !== null && args.count !== '') {
            params.count = requirePositiveInt(args.count, 'count', { max: 100 });
        }

        const payload = await callGateway('/store/search', params);
        const groups = Array.isArray(payload?.results) ? payload.results : [];
        if (groups.length === 0) {
            emptyResult('search', `No results for "${keyword}" (scope=${scopeKey}).`);
        }

        const rows = [];
        let rank = 0;
        for (const group of groups) {

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Check --help or SEARCH_SCOPES for exact accepted scope keys
  2. Use the default by omitting --scope entirely (defaults to 'ebook')
  3. Match casing exactly — validation is case-sensitive after trim only
  4. Normalize/whitelist scope values in your wrapper before invoking

Example fix

// before
await wereadSearch({ keyword, scope: 'Paper' });
// after
const scopes = ['ebook', 'paper', ...]; // per SEARCH_SCOPES
const s = String(scope ?? 'ebook').trim();
if (!scopes.includes(s)) throw new Error(`scope must be one of: ${scopes.join(', ')}`);
await wereadSearch({ keyword, scope: s });
Defensive patterns

Strategy: validation

Validate before calling

const SCOPES = ['ebook','paper']; // mirror SEARCH_SCOPES
if (!SCOPES.includes(String(scope ?? 'ebook').trim())) throw new Error(`scope must be one of: ${SCOPES.join(', ')}`);

Type guard

function isValidScope(s) { return typeof s === 'string' && Object.keys(SEARCH_SCOPES).includes(s.trim()); }

Try / catch

try { await wereadSearch(args); }
catch (e) { if (e.name === 'ArgumentError' && e.message.includes('scope must be')) { printAllowedScopes(); } else throw e; }

Prevention

When it happens

Trigger: Passing `--scope` values not in SEARCH_SCOPES: typos ('ebooks'), wrong casing ('Ebook'), or scopes from other tools that aren't supported; passing an empty-but-nonnull value that isn't the default after trim fails to match.

Common situations: Copy-pasted flags from documentation of a different weread client; scripts parameterizing scope from config with stale values; users assuming plural or capitalized forms are accepted.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/cf8b4fa1ba0d2e62. Report an issue: GitHub.