{"record":{"id":"13355f20a051baf7","repo":"jackwener/OpenCLI","slug":"archive-search-mediatype-must-be-one-of-mediatyp","errorCode":null,"errorMessage":"archive search mediatype must be one of ${MEDIATYPES.join(', ')}","messagePattern":"archive search mediatype must be one of (.+?)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/archive/search.js","lineNumber":36,"sourceCode":"    description: 'Search Internet Archive items across books, movies, audio, software, and web.',\n    domain: 'archive.org',\n    strategy: Strategy.PUBLIC,\n    browser: false,\n    args: [\n        { name: 'query', positional: true, required: true, help: 'Full-text query (matches title, description, creator, subject).' },\n        { name: 'mediatype', type: 'string', required: false, help: `Restrict to mediatype: ${MEDIATYPES.join(', ')}` },\n        { name: 'sort', type: 'string', default: 'downloads', help: `Sort key: ${SORT_OPTIONS.join(', ')}` },\n        { name: 'limit', type: 'int', default: 20, help: 'Max items (max 100; one API page).' },\n    ],\n    columns: ['rank', 'identifier', 'title', 'creator', 'date', 'mediatype', 'downloads', 'url'],\n    func: async (args) => {\n        const sortRaw = String(args.sort ?? 'downloads').toLowerCase();\n        const sort = SORT_ALIAS[sortRaw] ?? sortRaw;\n        if (!SORT_OPTIONS.includes(sort)) {\n            throw new ArgumentError(`archive search sort must be one of ${SORT_OPTIONS.join(', ')}`);\n        }\n        if (args.mediatype && !MEDIATYPES.includes(String(args.mediatype))) {\n            throw new ArgumentError(`archive search mediatype must be one of ${MEDIATYPES.join(', ')}`);\n        }\n        const limit = Number(args.limit ?? 20);\n        if (!Number.isInteger(limit) || limit <= 0) {\n            throw new ArgumentError('archive search limit must be a positive integer');\n        }\n        if (limit > 100) {\n            throw new ArgumentError('archive search limit must be <= 100');\n        }\n\n        const query = String(args.query ?? '').trim();\n        if (!query) {\n            throw new ArgumentError('archive search query must not be empty');\n        }\n\n        const fullQuery = args.mediatype\n            ? `(${query}) AND mediatype:${args.mediatype}`\n            : query;\n","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/archive/search.js#L18-L54","documentation":"This ArgumentError is thrown before any network call by `archive search` when a `mediatype` argument is supplied but is not one of MEDIATYPES ('texts', 'movies', 'audio', 'software', 'image', 'web', 'data', 'collection'). Unlike sort, no aliasing or lowercasing is applied to mediatype, so case must match exactly. It is purely client-side validation of the filter argument.","triggerScenarios":"Calling `opencli archive search <query> --mediatype <value>` where <value> is not an exact member of the whitelist — e.g. --mediatype Books, --mediatype text (singular), --mediatype video (not in list), or --mediatype ebooks.","commonSituations":"Guessing mediatype names ('book', 'movie' singular, 'video'); copying taxonomy labels from the archive.org UI instead of its API enum values; forgetting that the check is case-sensitive so 'Texts' fails.","solutions":["Use an exact whitelisted value: texts, movies, audio, software, image, web, data, collection","Fix casing — mediatype is matched case-sensitively, so use lowercase plural forms","Omit --mediatype to search across all mediatypes"],"exampleFix":"// before\nopencli archive search \"sherlock holmes\" --mediatype Books\n// after\nopencli archive search \"sherlock holmes\" --mediatype texts","handlingStrategy":"validation","validationCode":"const MEDIATYPES = ['texts','movies','audio','software','image','web','data','collection'];\nif (mediatype && !MEDIATYPES.includes(String(mediatype))) {\n    throw new Error(`mediatype must be one of ${MEDIATYPES.join(', ')}`);\n}","typeGuard":"const isMediatype = (m) => ['texts','movies','audio','software','image','web','data','collection'].includes(m);","tryCatchPattern":"try {\n    rows = await run(['archive', 'search', query, '--mediatype', mediatype]);\n} catch (err) {\n    if (err instanceof ArgumentError && err.message.includes('mediatype must be one of')) {\n        rows = await run(['archive', 'search', query]); // search without mediatype filter\n    } else { throw err; }\n}","preventionTips":["Use the exact lowercase plural enum values from the CLI help","Remember the check is case-sensitive — never pass 'Texts' or 'Book'","Drop the --mediatype flag to search all mediatypes","Centralize the mediatype enum in your own code instead of hardcoding strings ad hoc"],"tags":["validation","cli","argument-error","input"],"backgroundTag":"invalid-argument-value","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}