nexu-io/open-design · error · RangeError
OD_CRITIQUE_SCORE_THRESHOLD (${scoreThreshold}) must be <= O
Error message
OD_CRITIQUE_SCORE_THRESHOLD (${scoreThreshold}) must be <= OD_CRITIQUE_SCORE_SCALE (${scoreScale}) What it means
Thrown by loadCritiqueConfigFromEnv() as a RangeError when OD_CRITIQUE_SCORE_THRESHOLD is greater than OD_CRITIQUE_SCORE_SCALE (with a 1e-9 tolerance). It is a cross-field validation: scores produced by the panel are scaled against scoreScale, so a threshold above the scale would be unreachable and every run would be flagged sub-threshold. The check runs at config load so misconfiguration surfaces at boot, never silently.
Source
Thrown at apps/daemon/src/critique/config.ts:26
* surfaces at boot, never silently.
*
* @see specs/current/critique-theater.md § Configuration (env vars)
*/
export function loadCritiqueConfigFromEnv(env: NodeJS.ProcessEnv = process.env): CritiqueConfig {
const defaults = defaultCritiqueConfig();
const enabled = parseEnabled(env['OD_CRITIQUE_ENABLED'], defaults.enabled);
const maxRounds = parsePositiveInt('OD_CRITIQUE_MAX_ROUNDS', env['OD_CRITIQUE_MAX_ROUNDS'], defaults.maxRounds);
const scoreThreshold = parseNonNegativeFloat('OD_CRITIQUE_SCORE_THRESHOLD', env['OD_CRITIQUE_SCORE_THRESHOLD'], defaults.scoreThreshold);
const scoreScale = parsePositiveInt('OD_CRITIQUE_SCORE_SCALE', env['OD_CRITIQUE_SCORE_SCALE'], defaults.scoreScale);
const perRoundTimeoutMs = parsePositiveInt('OD_CRITIQUE_PER_ROUND_TIMEOUT_MS', env['OD_CRITIQUE_PER_ROUND_TIMEOUT_MS'], defaults.perRoundTimeoutMs);
const totalTimeoutMs = parsePositiveInt('OD_CRITIQUE_TOTAL_TIMEOUT_MS', env['OD_CRITIQUE_TOTAL_TIMEOUT_MS'], defaults.totalTimeoutMs);
const parserMaxBlockBytes = parsePositiveInt('OD_CRITIQUE_PARSER_MAX_BLOCK_BYTES', env['OD_CRITIQUE_PARSER_MAX_BLOCK_BYTES'], defaults.parserMaxBlockBytes);
const fallbackPolicy = parseFallbackPolicy(env['OD_CRITIQUE_FALLBACK_POLICY'], defaults.fallbackPolicy);
// Cross-field validation: threshold cannot exceed scale.
if (scoreThreshold > scoreScale + 1e-9) {
throw new RangeError(
`OD_CRITIQUE_SCORE_THRESHOLD (${scoreThreshold}) must be <= OD_CRITIQUE_SCORE_SCALE (${scoreScale})`,
);
}
return {
...defaults,
enabled,
maxRounds,
scoreThreshold,
scoreScale,
perRoundTimeoutMs,
totalTimeoutMs,
parserMaxBlockBytes,
fallbackPolicy,
};
}
// ---------------------------------------------------------------------------View on GitHub (pinned to 5be4028344)
Solutions
- Set OD_CRITIQUE_SCORE_THRESHOLD <= OD_CRITIQUE_SCORE_SCALE (e.g. threshold 8 with scale 10, or threshold 80 with scale 100).
- Decide on one scale convention (0-10 or 0-100) and set both vars consistently.
- Leave both unset to use defaultCritiqueConfig(), which already satisfies the constraint.
Example fix
# before: threshold above scale OD_CRITIQUE_SCORE_THRESHOLD=90 OD_CRITIQUE_SCORE_SCALE=10 # after: keep threshold within scale OD_CRITIQUE_SCORE_THRESHOLD=8 OD_CRITIQUE_SCORE_SCALE=10
Defensive patterns
Strategy: validation
Validate before calling
const threshold = Number(process.env.OD_CRITIQUE_SCORE_THRESHOLD ?? defaultThreshold);
const scale = Number(process.env.OD_CRITIQUE_SCORE_SCALE ?? defaultScale);
if (threshold > scale + 1e-9) {
throw new RangeError(`threshold ${threshold} must be <= scale ${scale}`);
} Type guard
function thresholdWithinScale(threshold: number, scale: number): boolean {
return threshold <= scale + 1e-9;
} Try / catch
try { loadCritiqueConfigFromEnv(); }
catch (e) {
if (e instanceof RangeError && /SCORE_THRESHOLD/.test(e.message)) {
// log, fall back to defaults, or fail boot per policy
} else throw e;
} Prevention
- Document the scale convention (0-10 vs 0-100) next to both env vars.
- Add a config-lint check in CI that asserts threshold <= scale for templated env files.
- Use defaultCritiqueConfig() unless you deliberately need to override both.
When it happens
Trigger: Setting OD_CRITIQUE_SCORE_THRESHOLD to a value larger than OD_CRITIQUE_SCORE_SCALE in the environment — e.g. THRESHOLD=90 with SCALE=10.
Common situations: Operator confused scale (e.g. 0-10 vs 0-100); copy-pasted env from another deployment with a different scale; threshold bumped without scaling the scale to match.
Related errors
- ${key} must be a positive integer, got "${raw}"
- ${key} must be a non-negative finite number, got "${raw}"
- OD_CRITIQUE_FALLBACK_POLICY must be one of ${FALLBACK_POLICI
- OD_DATA_DIR is required when OD_SANDBOX_MODE is enabled
- WORKSPACE_AUTHORITY_UNAVAILABLE
AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12).
Data as JSON: /api/errors/ea9dd08a75af42b1.
Report an issue: GitHub.