{"record":{"id":"97ebb810cb0b2ec3","repo":"jackwener/OpenCLI","slug":"limit-must-be-an-integer-between-1-and-15-dianpin","errorCode":null,"errorMessage":"limit must be an integer between 1 and 15 (dianping single page)","messagePattern":"limit must be an integer between 1 and 15 \\(dianping single page\\)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/dianping/utils.js","lineNumber":71,"sourceCode":"    if (cityArg == null || cityArg === '') return null;\n    const raw = String(cityArg).trim().toLowerCase();\n    if (/^\\d+$/.test(raw)) return Number(raw);\n    const id = CITY_ID[raw];\n    if (!id) {\n        const names = Object.keys(CITY_ID).filter((k) => /^[a-z]+$/.test(k)).join(', ');\n        throw new ArgumentError(\n            'city',\n            `unknown city '${cityArg}'. pass a numeric cityId or one of: ${names}`,\n        );\n    }\n    return id;\n}\n\nexport function requireSearchLimit(value) {\n    const raw = value == null || value === '' ? 15 : value;\n    const limit = typeof raw === 'number' ? raw : Number(String(raw).trim());\n    if (!Number.isInteger(limit) || limit < 1 || limit > 15) {\n        throw new ArgumentError('limit must be an integer between 1 and 15 (dianping single page)');\n    }\n    return limit;\n}\n\nexport function normalizeShopId(rawInput) {\n    const raw = String(rawInput || '').trim();\n    if (!raw) throw new ArgumentError('shop_id must be a non-empty string');\n\n    const idMatch = raw.match(/\\/shop\\/([^?#/]+)/);\n    const shopId = idMatch ? idMatch[1] : raw;\n    if (!/^[A-Za-z0-9_-]+$/.test(shopId)) {\n        throw new ArgumentError(`'${raw}' does not look like a dianping shop id`);\n    }\n    return shopId;\n}\n\nexport function wrapDianpingStep(label, fn) {\n    return Promise.resolve()","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/dianping/utils.js#L53-L89","documentation":"requireSearchLimit validates the search limit against dianping's single-page constraint: the PC search page returns at most 15 results per request, so limits must be integers from 1 to 15. Non-integers (including strings that parse to non-integers or NaN), zero, negatives, and values above 15 all throw this ArgumentError. An empty/missing value defaults to 15.","triggerScenarios":"Passing limit=16 or higher (e.g. expecting pagination to be automatic), passing limit=0 or a negative number, passing a non-numeric string like 'all' or '10个', or a decimal like 2.5.","commonSituations":"Assuming the CLI paginates automatically for larger limits; copying a limit from another API that allows 50/100; CLI flag passed as free text; script reading limit from config where it was stored as '20'.","solutions":["Use an integer between 1 and 15; omit the flag entirely to get the default of 15.","If you need more than 15 results, run multiple searches (e.g. vary keyword or page/city offsets) and merge the rows yourself.","Coerce and clamp the value before calling: Math.min(15, Math.max(1, Math.round(Number(raw)))).","Validate the config/CLI input source so it cannot supply non-numeric text."],"exampleFix":"// before\nrequireSearchLimit('20'); // ArgumentError\n// after\nconst n = Math.min(15, Math.max(1, Math.round(Number(raw))));\nrequireSearchLimit(n); // ok, capped to 15","handlingStrategy":"validation","validationCode":"function isValidLimit(v) {\n  if (v == null || v === '') return true; // defaults to 15\n  const n = typeof v === 'number' ? v : Number(String(v).trim());\n  return Number.isInteger(n) && n >= 1 && n <= 15;\n}","typeGuard":"function isSearchLimit(v) {\n  return typeof v === 'number' && Number.isInteger(v) && v >= 1 && v <= 15;\n}","tryCatchPattern":"try {\n  const limit = requireSearchLimit(rawLimit);\n} catch (e) {\n  if (e.name === 'ArgumentError' && /between 1 and 15/.test(e.message)) {\n    console.error(`limit '${rawLimit}' invalid; clamping to default range 1-15`);\n  } else throw e;\n}","preventionTips":["Clamp user/config input: Math.min(15, Math.max(1, Math.round(Number(v)))).","Remember dianping PC search is single-page: >15 requires multiple queries, not a bigger limit.","Parse CLI flags as integers at the boundary, rejecting non-numeric strings early.","Unit-test limit handling with edge values (0, 1, 15, 16, 'abc')."],"tags":["validation","argument-error","limit"],"backgroundTag":"invalid-argument-value","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}