Skip to content

feat(cli): warn when lambda --width/--height conflicts with composition#1022

Merged
jrusso1020 merged 2 commits into
mainfrom
feat/lambda-render-warn-on-dimension-mismatch
May 22, 2026
Merged

feat(cli): warn when lambda --width/--height conflicts with composition#1022
jrusso1020 merged 2 commits into
mainfrom
feat/lambda-render-warn-on-dimension-mismatch

Conversation

@jrusso1020
Copy link
Copy Markdown
Collaborator

@jrusso1020 jrusso1020 commented May 21, 2026

What

Warn early when hyperframes lambda render / render-batch is passed --width/--height values that disagree with the composition's authored data-width/data-height. Points the user at --output-resolution (PR #1020) — the supported supersampling escape hatch.

Why

This is a real footgun I hit during the cost-analysis sweep. I passed --width 3840 --height 2160 to render a 1080p composition at 4K, the command succeeded after 8 minutes, and the output was still 1080p. The runtime lays out the page at the composition's authored data-width / data-height — Config.width is ignored on disagreement, silently. A 30-minute render later you learn what data-* does.

The warning catches this at CLI dispatch time (~5ms before any AWS call) and tells the user how to actually get the higher resolution.

How

  • New warnOnDimensionMismatch helper in packages/cli/src/commands/lambda/_dimensions.ts, called from both runRender and runRenderBatch (in render-batch it fires once before the per-entry loop — a 1000-row batch with wrong dimensions burns the bug across every entry).
  • Reuse: delegates HTML parsing to the existing findCompositionDimensions helper added to packages/cli/src/utils/compositionViewport.ts (a thin null-returning variant of resolveCompositionViewportFromHtml, which already powers validate + snapshot and uses the same [data-composition-id][data-width][data-height] selector the producer uses to lay out the page). No regex parallel-parser.
  • Suppressed when --output-resolution is set (user has opted in to supersampling), when --json is set (machine consumers parse the manifest), or when index.html isn't on disk (typical with --site-id pointing at a pre-uploaded site).
  • Single try { readFileSync } — no existsSync TOCTOU.

Test plan

  • Unit tests: warning fires on mismatch · silent on match · silent under --output-resolution · silent under --json · silent when index.html missing · silent when composition has no data-composition-id root.
  • Typecheck + format + lint clean.
  • Manual: passing --width 3840 --height 2160 against a 1080p composition prints the warning + suggestion before the render starts.

miguel-heygen
miguel-heygen previously approved these changes May 22, 2026
Copy link
Copy Markdown
Collaborator

@miguel-heygen miguel-heygen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean, well-scoped PR. The refactoring of findCompositionDimensions out of resolveCompositionViewportFromHtml is semantically correct — the null-returning variant delegates cleanly and the fallback in the original function is preserved. Edge cases are thoroughly covered: missing index.html, absent composition root, --output-resolution suppression, --json quiet mode. Integration into both render.ts and render-batch.ts threads through the right fields.

No issues found.

@jrusso1020 jrusso1020 force-pushed the fix/lambda-progress-cost-task-events branch from 3b64fab to aa95ee0 Compare May 22, 2026 18:02
@jrusso1020 jrusso1020 force-pushed the feat/lambda-render-warn-on-dimension-mismatch branch from 628cce0 to 370a42f Compare May 22, 2026 18:02
vanceingalls
vanceingalls previously approved these changes May 22, 2026
Copy link
Copy Markdown
Collaborator

@vanceingalls vanceingalls left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blockers. _dimensions.ts helper is well-isolated, the --json/--output-resolution suppression is thorough, and the 6 test cases cover all suppression conditions cleanly.

Important

resolveCompositionViewportFromHtml has a subtle behavioral change. Old code defaulted width and height independently (width ?? DEFAULT.width, height ?? DEFAULT.height). New code: findCompositionDimensions(html) ?? DEFAULT_VIEWPORT — if either parsed dimension is null, both fall back to defaults as a pair. Since the CSS selector requires all three attributes ([data-composition-id][data-width][data-height]), the only path to a null parse is a malformed attribute value (e.g., data-width="abc"). The new behavior is arguably more correct (coherent defaults over partial defaulting), but validate and snapshot both call this function in production paths. Please add a test for the partial-invalid-attribute edge case to document and lock in the new semantics. Without it, the semantic change is untested and invisible to future readers.

Nits

  • fallow-ignore-next-line complexity on warnOnDimensionMismatch adds noise — the function is ~20 lines and straightforward; consider removing the suppressor.
  • Warning copy "edit the composition's data-width/data-height in index.html" is a footgun if the user has a build step that generates index.html. Consider softening to "edit the composition's authored dimensions."

Note: Stacked — Build/Test/Typecheck/Lint did not run on this PR head.

— Vai

@jrusso1020 jrusso1020 force-pushed the feat/lambda-render-warn-on-dimension-mismatch branch from 370a42f to b5bf5dc Compare May 22, 2026 18:47
@jrusso1020 jrusso1020 force-pushed the fix/lambda-progress-cost-task-events branch 2 times, most recently from 582af7b to 3033d01 Compare May 22, 2026 19:08
jrusso1020 and others added 2 commits May 22, 2026 19:09
The CDK construct compiles tasks.LambdaInvoke to the optimized
arn:aws:states:::lambda:invoke integration, which emits Task* history
events with the Lambda response wrapped in .Payload. getRenderProgress
was only listening for the older LambdaFunction* events, so every CDK-
deployed stack reported $0 total cost and zero invocations on success
— a high-visibility regression that only surfaced when we manually
walked SFN history during a cost-analysis sweep.

Add cases for TaskScheduled (count invocation), TaskSucceeded (parse
Payload + accumulate billed duration / frame counts), and TaskFailed
(record error). Keep the LambdaFunction* paths so anyone wiring the
raw lambda:invokeFunction.sync task type still works. Factor out the
shared FramesEncoded-attribution logic so both branches agree on the
"only RenderChunk frames count" rule.

Tests pin a real-shape regression: replay the inspector-launch
1080p/30fps history (1 Plan + 16 RenderChunks + 1 Assemble) and assert
lambdaUsd lands at ~$0.582 — matching the cost-analysis script's
direct read against SFN history.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`--width 3840 --height 2160` against a composition with
`data-width="1920"` silently produces a 1080p output because the
runtime lays out the page at the composition's authored dimensions —
real footgun we hit during a cost-analysis sweep. Warn early and point
at `--output-resolution` (the supersampling escape hatch) so the user
doesn't burn a 30-minute render learning the override rule.

Skipped when `--output-resolution` is set (the supported supersampling
path — the user is opting in), when `--json` is set (machine consumers),
or when `index.html` isn't on disk (typical with `--site-id`).

Helper lives in a shared module so render + render-batch agree on the
parse + message. Tests cover both attribute orders, single/double
quotes, the silent paths, and the warning path. Best-effort regex over
the canonical attr shape — malformed HTML falls through to no warning
rather than blocking the render.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@jrusso1020 jrusso1020 force-pushed the fix/lambda-progress-cost-task-events branch from 3033d01 to 36ddd48 Compare May 22, 2026 19:09
@jrusso1020 jrusso1020 force-pushed the feat/lambda-render-warn-on-dimension-mismatch branch from b5bf5dc to 37ecdad Compare May 22, 2026 19:09
Base automatically changed from fix/lambda-progress-cost-task-events to main May 22, 2026 20:29
@jrusso1020 jrusso1020 dismissed stale reviews from vanceingalls and miguel-heygen May 22, 2026 20:29

The base branch was changed.

Copy link
Copy Markdown
Collaborator

@miguel-heygen miguel-heygen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved — no issues found in review.

@jrusso1020 jrusso1020 merged commit ec1b7e1 into main May 22, 2026
32 checks passed
@jrusso1020 jrusso1020 deleted the feat/lambda-render-warn-on-dimension-mismatch branch May 22, 2026 20:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants