jackwener/OpenCLI · error

Invalid trace maxCountPerProfile: ${maxCountPerProfile}

Error message

Invalid trace maxCountPerProfile: ${maxCountPerProfile}

What it means

resolveTraceRetentionPolicy() requires maxCountPerProfile to be a non-negative integer because it caps how many traces are kept per profile. This Error is thrown when the value is fractional (e.g. 10.5), negative, or otherwise not an integer. Complements the maxAgeDays check with the same fail-fast policy.

Source

Thrown at src/observation/retention.ts:63

export function parseByteSize(value: string | number): number {
  if (typeof value === 'number') {
    if (!Number.isFinite(value) || value < 0) throw new Error(`Invalid byte size: ${value}`);
    return Math.floor(value);
  }
  const match = value.trim().match(/^(\d+(?:\.\d+)?)\s*(B|KB|MB|GB)?$/i);
  if (!match) throw new Error(`Invalid byte size: ${value}`);
  const amount = Number(match[1]);
  const unit = (match[2] ?? 'B').toUpperCase();
  return Math.floor(amount * BYTES_UNITS[unit]);
}

export function resolveTraceRetentionPolicy(input: TraceRetentionPolicyInput = {}): ResolvedTraceRetentionPolicy {
  const maxAgeDays = input.maxAgeDays ?? DEFAULT_TRACE_RETENTION_POLICY.maxAgeDays;
  const maxCountPerProfile = input.maxCountPerProfile ?? DEFAULT_TRACE_RETENTION_POLICY.maxCountPerProfile;
  if (!Number.isFinite(maxAgeDays) || maxAgeDays < 0) throw new Error(`Invalid trace maxAgeDays: ${maxAgeDays}`);
  if (!Number.isInteger(maxCountPerProfile) || maxCountPerProfile < 0) {
    throw new Error(`Invalid trace maxCountPerProfile: ${maxCountPerProfile}`);
  }
  return {
    maxAgeDays,
    maxAgeMs: maxAgeDays * 24 * 60 * 60 * 1000,
    maxCountPerProfile,
    maxBytesPerProfile: parseByteSize(input.maxBytesPerProfile ?? DEFAULT_TRACE_RETENTION_POLICY.maxBytesPerProfile),
  };
}

export function traceExpiresAt(createdAt: string, policyInput: TraceRetentionPolicyInput = {}): string {
  const policy = resolveTraceRetentionPolicy(policyInput);
  const createdAtMs = Date.parse(createdAt);
  const base = Number.isFinite(createdAtMs) ? createdAtMs : Date.now();
  return new Date(base + policy.maxAgeMs).toISOString();
}

export function pruneTraceArtifacts(
  tracesDir: string,

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Round the value: Math.floor/Math.round to a non-negative integer before passing it.
  2. Fix the upstream calculation or config so the count is a whole non-negative number.
  3. Omit maxCountPerProfile to fall back to DEFAULT_TRACE_RETENTION_POLICY.maxCountPerProfile.

Example fix

// before
resolveTraceRetentionPolicy({ maxCountPerProfile: totalTraces / profileCount }) // may be fractional
// after
resolveTraceRetentionPolicy({ maxCountPerProfile: Math.max(0, Math.floor(totalTraces / profileCount)) })
Defensive patterns

Strategy: validation

Validate before calling

function isValidMaxCountPerProfile(v) {
  return typeof v === 'number' && Number.isInteger(v) && v >= 0;
}
// if (!isValidMaxCountPerProfile(cfg.maxCountPerProfile)) cfg.maxCountPerProfile = undefined; // use default

Type guard

function isMaxCountPerProfile(v: unknown): v is number {
  return typeof v === 'number' && Number.isInteger(v) && v >= 0;
}

Try / catch

try {
  return resolveTraceRetentionPolicy(input);
} catch (e) {
  if (e instanceof Error && e.message.includes('maxCountPerProfile')) {
    logger.warn(`Bad maxCountPerProfile ${String(input?.maxCountPerProfile)}, falling back to defaults`);
    return resolveTraceRetentionPolicy({ ...input, maxCountPerProfile: undefined });
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling resolveTraceRetentionPolicy({ maxCountPerProfile: -5 }) or { maxCountPerProfile: 100.5 }; also NaN/Infinity which fail Number.isInteger.

Common situations: Config values divided or averaged at runtime (e.g. total/profiles producing fractions), a negative from a bad formula, or a percent-like value ('50%') parsed loosely in JS.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/3bc606eee6d05100. Report an issue: GitHub.