tinyhumansai/openhuman · error · Error
${label} must be a non-negative number
Error message
${label} must be a non-negative number What it means
parseNonNegativeNumber() accepts any finite number >= 0 (fractions allowed) and throws with the label otherwise. In harness-cache-audit.mjs it guards --min-hit-rate, the aggregate cached/input ratio threshold in percent below which the audit exits non-zero. Non-numeric strings become NaN and fail Number.isFinite; negatives fail the < 0 check.
Source
Thrown at scripts/debug/harness-cache-audit.mjs:152
function parsePositiveInt(raw, label) {
const value = Number(raw);
if (!Number.isInteger(value) || value < 1)
throw new Error(`${label} must be a positive integer`);
return value;
}
function parseNonNegativeInt(raw, label) {
const value = Number(raw);
if (!Number.isInteger(value) || value < 0)
throw new Error(`${label} must be a non-negative integer`);
return value;
}
function parseNonNegativeNumber(raw, label) {
const value = Number(raw);
if (!Number.isFinite(value) || value < 0)
throw new Error(`${label} must be a non-negative number`);
return value;
}
function defaultOpenhumanDir() {
return process.env.OPENHUMAN_APP_ENV === "staging"
? path.join(homedir(), ".openhuman-staging")
: path.join(homedir(), ".openhuman");
}
async function defaultWorkspace() {
if (process.env.OPENHUMAN_WORKSPACE) return process.env.OPENHUMAN_WORKSPACE;
const openhumanDir = defaultOpenhumanDir();
try {
const active = await readFile(
path.join(openhumanDir, "active_user.toml"),
"utf8",
);
const match = active.match(/^\s*user_id\s*=\s*"([^"]+)"\s*$/m);View on GitHub (pinned to a221052e0d)
Solutions
- Pass a plain percent number: `--min-hit-rate 20` for 20%
- Drop the % sign and any units
- Remember the unit is percent, not a 0-1 ratio
- Guard wrappers with a numeric regex before composing the command
Example fix
# before node scripts/debug/harness-cache-audit.mjs --min-hit-rate 20% # Error: --min-hit-rate must be a non-negative number # after node scripts/debug/harness-cache-audit.mjs --min-hit-rate 20
Defensive patterns
Strategy: validation
Validate before calling
const toNonNegativeNumber = (raw, label) => {
const n = Number(raw);
if (!Number.isFinite(n) || n < 0) {
console.error(`${label} must be a number >= 0, no % or units (got: ${raw})`);
process.exit(2);
}
return n;
};
const minHitRate = toNonNegativeNumber(process.env.MIN_HIT_RATE ?? "1", "--min-hit-rate"); Type guard
const isNonNegativeNumberString = (s) => /^\d+(\.\d+)?$/.test(String(s).trim());
Prevention
- The unit of --min-hit-rate is percent: pass 20, not 0.2 and not 20%
- Strip % and units when copying thresholds from dashboards or notes
When it happens
Trigger: `--min-hit-rate -5`, `--min-hit-rate abc`, `--min-hit-rate 20%` (trailing % makes it NaN), `--min-hit-rate Infinity` (not finite); an unset env var interpolated as the bare text of the flag's value in a wrapper.
Common situations: Percent sign copied along with the number; comma decimal (`0,5`); intending a ratio (0.2) where a percent (20) is expected — legal but semantically off, so the audit silently passes/fails unexpectedly; wrapper variable typos.
Related errors
- ${label} must be a positive integer
- ${label} must be a non-negative integer
- Failed to parse service CLI output as JSON: parsed value doe
- paths must be repo-relative, not absolute (got "${p}")
- must be an array
AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16).
Data as JSON: /api/errors/ec24098d0134963d.
Report an issue: GitHub.