heygen-com/hyperframes · error · Error
Exactly one of --grades or --luts is required
Error message
Exactly one of --grades or --luts is required
What it means
Thrown by parseGradeCompareArgs when `--grades` and `--luts` are either both supplied or both absent (`Boolean(gradesArg) === Boolean(lutsArg)` covers both true and both false). The command needs exactly one source of candidate looks — a grades JSON file or a comma-separated LUT list — because mixing them would be ambiguous and supplying neither leaves nothing to render.
Source
Thrown at packages/cli/src/commands/grade-compare.ts:274
return [validateCell("original", {}), ...cells];
}
export function parseGradeCompareArgs(args: {
for?: unknown;
grades?: unknown;
luts?: unknown;
project?: unknown;
out?: unknown;
json?: unknown;
timeout?: unknown;
}): ParsedGradeCompareArgs {
const frameArg = readOptionalString(args.for);
if (!frameArg) throw new Error("--for <path> is required");
const gradesArg = readOptionalString(args.grades);
const lutsArg = readOptionalString(args.luts);
if (Boolean(gradesArg) === Boolean(lutsArg)) {
throw new Error("Exactly one of --grades or --luts is required");
}
const projectDir = resolve(readOptionalString(args.project) ?? process.cwd());
const framePath = resolveFromBase(projectDir, frameArg);
const outPath = resolveFromBase(projectDir, readOptionalString(args.out) ?? "grade-compare.png");
return {
framePath,
projectDir,
outPath,
source: gradesArg
? { kind: "grades", path: resolveFromBase(projectDir, gradesArg) }
: { kind: "luts", value: lutsArg ?? "" },
json: args.json === true,
timeoutMs: Number.parseInt(readOptionalString(args.timeout) ?? "", 10) || 5000,
};
}
View on GitHub (pinned to c2996c8626)
Solutions
- Pick one source: use `--grades grades.json` for inline-defined looks, or `--luts a.cube,b.cube` for .cube files.
- Remove whichever flag is unwanted from the command line.
- If neither is set, add the one that matches your asset type.
Example fix
# before (both) hyperframes grade-compare --for f.png --grades g.json --luts a.cube # after (pick one) hyperframes grade-compare --for f.png --grades g.json
Defensive patterns
Strategy: validation
Validate before calling
// Ensure exactly one source flag is set
function pickSource(grades?: string, luts?: string): "grades" | "luts" {
const g = Boolean(grades), l = Boolean(luts);
if (g === l) throw new Error("Pass exactly one of --grades or --luts");
return g ? "grades" : "luts";
} Type guard
function exactlyOneSet(a: unknown, b: unknown): boolean {
return Boolean(a) !== Boolean(b);
} Try / catch
try {
const parsed = parseGradeCompareArgs(args);
} catch (err) {
if (/Exactly one of/.test((err as Error).message)) {
console.error("Choose either --grades <file> or --luts <list>, not both/neither.");
}
throw err;
} Prevention
- Standardize your team on one mode (--grades) and document a single canonical command shape.
- In CI, fail fast if BOTH env-supplied values are non-empty.
- Use exactlyOneSet in a pre-flight check when templating commands.
When it happens
Trigger: Running grade-compare with both `--grades grades.json --luts a.cube`; or with neither flag; or with both empty strings.
Common situations: Copy-pasting a command that evolved from one mode to the other; CI templates that conditionally set both; forgetting which mode you intended.
Related errors
- Grade entry "${label}" must include a grading value
- --luts must include at least one LUT path
- --for <path> is required
- At least one grade cell is required
- Reference frame not found: ${framePath}
AI-assisted analysis of heygen-com/hyperframes@c2996c8626 (2026-08-12).
Data as JSON: /api/errors/67723b35e46f1698.
Report an issue: GitHub.