{"record":{"id":"0a7ae17c42718f03","repo":"nexu-io/open-design","slug":"key-must-be-a-non-negative-finite-number-got","errorCode":null,"errorMessage":"${key} must be a non-negative finite number, got \"${raw}\"","messagePattern":"(.+?) must be a non-negative finite number, got \"(.+?)\"","errorType":"validation","errorClass":"RangeError","httpStatus":null,"severity":"error","filePath":"apps/daemon/src/critique/config.ts","lineNumber":69,"sourceCode":"  return v === 'true' || v === '1' || v === 'yes';\n}\n\nfunction parsePositiveInt(key: string, raw: string | undefined, fallback: number): number {\n  if (raw === undefined) return fallback;\n  const n = Number(raw);\n  if (!Number.isFinite(n) || !Number.isInteger(n) || n < 1) {\n    throw new RangeError(\n      `${key} must be a positive integer, got \"${raw}\"`,\n    );\n  }\n  return n;\n}\n\nfunction parseNonNegativeFloat(key: string, raw: string | undefined, fallback: number): number {\n  if (raw === undefined) return fallback;\n  const n = Number(raw);\n  if (!Number.isFinite(n) || n < 0) {\n    throw new RangeError(\n      `${key} must be a non-negative finite number, got \"${raw}\"`,\n    );\n  }\n  return n;\n}\n\nfunction parseFallbackPolicy(\n  raw: string | undefined,\n  fallback: CritiqueConfig['fallbackPolicy'],\n): CritiqueConfig['fallbackPolicy'] {\n  if (raw === undefined) return fallback;\n  const trimmed = raw.trim();\n  if (FALLBACK_POLICIES.includes(trimmed as CritiqueConfig['fallbackPolicy'])) {\n    return trimmed as CritiqueConfig['fallbackPolicy'];\n  }\n  throw new RangeError(\n    `OD_CRITIQUE_FALLBACK_POLICY must be one of ${FALLBACK_POLICIES.join(', ')}, got \"${raw}\"`,\n  );","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/nexu-io/open-design/blob/5be4028344c2eb4c667c5a97bda8f750c5597ef7/apps/daemon/src/critique/config.ts#L51-L87","documentation":"Thrown by parseNonNegativeFloat() (used by loadCritiqueConfigFromEnv for OD_CRITIQUE_SCORE_THRESHOLD) as a RangeError when the value is set but is not a finite number >= 0 (negative, NaN, Infinity, or non-numeric). ${key} is always 'OD_CRITIQUE_SCORE_THRESHOLD' in current usage; ${raw} is the offending input. Threshold is a float because panel scores are continuous.","triggerScenarios":"Setting OD_CRITIQUE_SCORE_THRESHOLD to a negative number, NaN, Infinity, or a non-numeric string. e.g. OD_CRITIQUE_SCORE_THRESHOLD=-1, OD_CRITIQUE_SCORE_THRESHOLD=high.","commonSituations":"Operator entered a negative threshold thinking it disables the gate; a templated value injected an empty string or 'auto'; locale-related comma decimal ('0,8') parsed to NaN.","solutions":["Set OD_CRITIQUE_SCORE_THRESHOLD to a non-negative finite number (e.g. 0.8, or 8 depending on scale) using a dot decimal.","Unset it to use the default threshold from defaultCritiqueConfig().","Ensure templated env files emit a plain numeric literal, not empty strings or localized decimals."],"exampleFix":"# before: negative / non-numeric / locale decimal\nOD_CRITIQUE_SCORE_THRESHOLD=-1\nOD_CRITIQUE_SCORE_THRESHOLD=0,8\n\n# after: non-negative finite, dot decimal\nOD_CRITIQUE_SCORE_THRESHOLD=0.8","handlingStrategy":"validation","validationCode":"function assertNonNegFloat(key: string, raw: string | undefined, fallback: number) {\n  if (raw === undefined) return fallback;\n  const n = Number(raw);\n  if (!Number.isFinite(n) || n < 0) {\n    throw new RangeError(`${key} must be a non-negative finite number, got \"${raw}\"`);\n  }\n  return n;\n}","typeGuard":"function isNonNegFloat(raw: unknown): raw is number {\n  return typeof raw === 'number' && Number.isFinite(raw) && raw >= 0;\n}","tryCatchPattern":"try { loadCritiqueConfigFromEnv(); }\ncatch (e) {\n  if (e instanceof RangeError && /non-negative/.test(e.message)) {\n    // fall back to defaults or fail boot\n  } else throw e;\n}","preventionTips":["Use dot decimals in env values (avoid locale-specific commas).","Validate numeric env in CI for templated configs.","Reject empty strings and 'auto' literals before they reach Number()."],"tags":["critique","config","env-vars","range-error","boot"],"backgroundTag":null,"analyzedSha":"5be4028344c2eb4c667c5a97bda8f750c5597ef7","analyzedAt":"2026-08-12T12:03:58.812Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}