tinyhumansai/openhuman · error · Error

${label} must be a non-negative integer

Error message

${label} must be a non-negative integer

What it means

parseNonNegativeInt() requires Number(raw) to be an integer >= 0 and throws with the label otherwise. In harness-cache-audit.mjs it guards --max-turns-without-cache, the audit failure threshold for how many completed turns may have zero cached input. Zero is allowed here (strictest setting), unlike the positive-int guard — the two validators are easy to confuse.

Source

Thrown at scripts/debug/harness-cache-audit.mjs:145

        process.exit(0);
      default:
        throw new Error(`unknown option: ${arg}`);
    }
  }
  return opts;
}

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;

View on GitHub (pinned to a221052e0d)

Solutions

  1. Use a whole number >= 0: `--max-turns-without-cache 0` means every turn must hit cache
  2. Strip units/quotes from the value
  3. Validate in the wrapper: `[[ $MAX =~ ^[0-9]+$ ]] || exit 1` before invoking

Example fix

# before
node scripts/debug/harness-cache-audit.mjs --max-turns-without-cache -1
# Error: --max-turns-without-cache must be a non-negative integer

# after
node scripts/debug/harness-cache-audit.mjs --max-turns-without-cache 0
Defensive patterns

Strategy: validation

Validate before calling

const toNonNegativeInt = (raw, label) => {
  const n = Number(raw);
  if (!Number.isInteger(n) || n < 0) {
    console.error(`${label} must be a whole number >= 0 (got: ${raw})`);
    process.exit(2);
  }
  return n;
};
const maxUncached = toNonNegativeInt(process.env.MAX_UNCACHED ?? "1", "--max-turns-without-cache");

Type guard

const isNonNegativeIntString = (s) => /^\d+$/.test(String(s).trim());

Prevention

When it happens

Trigger: `--max-turns-without-cache -1` (negative), `--max-turns-without-cache 1.5` (fractional), `--max-turns-without-cache many` (NaN), or a shell arithmetic expansion that failed and produced an empty/non-numeric token.

Common situations: Trying to express 'fail on any uncached turn' with -1 instead of 0; passing a percentage or a ratio where a count is expected; copy-paste from a notes file with a unit suffix ("2 turns").

Related errors


AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16). Data as JSON: /api/errors/b5a3d8f6cfc3dd6a. Report an issue: GitHub.