{"record":{"id":"db2b20dc6cbd0657","repo":"jackwener/OpenCLI","slug":"openreview-label-must-be-a-non-negative-integer","errorCode":null,"errorMessage":"openreview ${label} must be a non-negative integer","messagePattern":"openreview (.+?) must be a non-negative integer","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/openreview/utils.js","lineNumber":42,"sourceCode":"}\n\nexport function requireBoundedInt(value, defaultValue, maxValue, label = 'limit') {\n    const raw = value ?? defaultValue;\n    const n = coerceInt(raw);\n    if (!Number.isInteger(n) || n <= 0) {\n        throw new ArgumentError(`openreview ${label} must be a positive integer`);\n    }\n    if (n > maxValue) {\n        throw new ArgumentError(`openreview ${label} must be <= ${maxValue}`);\n    }\n    return n;\n}\n\nexport function requireNonNegativeInt(value, defaultValue, label = 'offset') {\n    const raw = value ?? defaultValue;\n    const n = coerceInt(raw);\n    if (!Number.isInteger(n) || n < 0) {\n        throw new ArgumentError(`openreview ${label} must be a non-negative integer`);\n    }\n    return n;\n}\n\nexport function requireForumId(value, label = 'id') {\n    const id = String(value ?? '').trim();\n    if (!id) {\n        throw new ArgumentError(`openreview ${label} is required`);\n    }\n    if (!ID_PATTERN.test(id)) {\n        throw new ArgumentError(`openreview ${label} \"${value}\" is not a valid forum id (expected 6-20 chars of [A-Za-z0-9_-])`);\n    }\n    return id;\n}\n\n/** OpenReview profile ids are `~...N` slugs and may include dots, hyphens, and Unicode letters. */\nconst PROFILE_ID_PATTERN = /^~(?=.*\\p{L})[\\p{L}\\p{M}0-9._-]+\\d+$/u;\n","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/openreview/utils.js#L24-L60","documentation":"requireNonNegativeInt validates offset-style options: the value must coerce to an integer >= 0. It is used for pagination offsets, so 0 is allowed but negatives and non-integers are rejected with ArgumentError before any API call.","triggerScenarios":"An offset argument (or whatever label is passed, default 'offset') coerces to a non-integer or a negative integer — e.g. --offset -10, --offset abc, --offset 1.5.","commonSituations":"Computing offsets as page*size with page starting at -1 or an unset variable; decrement loops underflowing below zero; string values with stray characters that coerceInt rejects; shell arithmetic producing negative results on the last page.","solutions":["Pass an integer >= 0, e.g. --offset 0","Clamp computed offsets: Math.max(0, page * pageSize)","Check the variable/expression feeding the offset for negative or empty values","Omit the flag to start from offset 0"],"exampleFix":"// before\nconst offset = (page - 1) * pageSize; // page=0 -> -25\n// after\nconst offset = Math.max(0, (page - 1) * pageSize);","handlingStrategy":"validation","validationCode":"const n = coerceInt(rawOffset);\nif (!Number.isInteger(n) || n < 0) {\n    throw new Error(`offset must be a non-negative integer, got: ${rawOffset}`);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Clamp computed offsets: Math.max(0, page * pageSize)","Guard pagination loops so the index never goes negative","Omit --offset for the first page (defaults to 0)","Validate numeric flags in wrapper scripts before invoking"],"tags":["argument-validation","pagination","cli","input-validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}