Skip to content

fix(core): skip re-application of manual layout instead of crashing#2883

Merged
davydkov merged 1 commit into
mainfrom
fix/manual-layout-crash
Apr 13, 2026
Merged

fix(core): skip re-application of manual layout instead of crashing#2883
davydkov merged 1 commit into
mainfrom
fix/manual-layout-crash

Conversation

@ckeller42

@ckeller42 ckeller42 commented Apr 11, 2026

Copy link
Copy Markdown
Collaborator

Summary

Fix for #2882 — views with manual layout snapshots crash on the interactive view route in dev mode.

Root Cause

The Vite dev server client receives view data where _layout is already 'manual', but LikeC4ViewModel.$manual unconditionally calls applyManualLayout() which throws an invariant on _layout === 'manual'.

Server-side: layoutedModel() returns _layout: 'auto' — correct. The Vite client pipeline modifies the value before rendering.

Fix

Guard in LikeC4ViewModel.$manual (packages/core/src/model/view/LikeC4ViewModel.ts): if this.#view._layout === 'manual', return this.#view directly — it already has current data + manual positions. The applyManualLayout invariant is preserved as a contract guard.

Before / After

  • Before: Navigating to /project/e2e/view/view-with-custom-colors/ shows red "Something went wrong" error screen with applyManualLayout: expected auto-layouted view
  • After: The view renders correctly with custom colors, nested containers, and edges

Test

Added e2e/tests/manual-layout-views.spec.ts — navigates to the interactive view route (/view/, not /export/) for view-with-custom-colors and verifies the diagram renders without the error boundary firing.

Files changed

  • packages/core/src/model/view/LikeC4ViewModel.ts — guard in $manual getter
  • e2e/tests/manual-layout-views.spec.ts — e2e regression test for interactive route
  • e2e/.gitignore — whitelist new test
  • .changeset/fix-manual-layout-crash.md — patch changeset

Closes #2882

🤖 Generated with Claude Code

@ckeller42 ckeller42 requested a review from davydkov April 11, 2026 20:49
@ckeller42

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@changeset-bot

changeset-bot Bot commented Apr 11, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 31ab78e

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 21 packages
Name Type
@likec4/core Patch
@likec4/playground Patch
@likec4/config Patch
@likec4/diagram Patch
@likec4/generators Patch
@likec4/language-server Patch
@likec4/language-services Patch
@likec4/layouts Patch
@likec4/leanix-bridge Patch
likec4 Patch
@likec4/mcp Patch
@likec4/react Patch
@likec4/vite-plugin Patch
@likec4/vscode-preview Patch
likec4-vscode Patch
@likec4/docs-astro Patch
@likec4/lsp Patch
@likec4/style-preset Patch
@likec4/styles Patch
@likec4/log Patch
@likec4/tsconfig Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai

coderabbitai Bot commented Apr 11, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Apr 11, 2026

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5a5834ab-3dd6-4ecb-b5d7-501a2cf45c22

📥 Commits

Reviewing files that changed from the base of the PR and between eafe583 and 31ab78e.

📒 Files selected for processing (4)
  • .changeset/fix-manual-layout-crash.md
  • e2e/.gitignore
  • e2e/tests/manual-layout-views.spec.ts
  • packages/core/src/model/view/LikeC4ViewModel.ts
✅ Files skipped from review due to trivial changes (3)
  • e2e/.gitignore
  • .changeset/fix-manual-layout-crash.md
  • e2e/tests/manual-layout-views.spec.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/core/src/model/view/LikeC4ViewModel.ts

📝 Walkthrough

Walkthrough

Adds a patch changeset and a guard in LikeC4ViewModel.$manual to avoid re-applying manual layout when view._layout === 'manual'; adds an E2E Playwright test and updates e2e/.gitignore so the test is run. (≤50 words)

Changes

Cohort / File(s) Summary
Changeset Documentation
\.changeset/fix-manual-layout-crash.md
New changeset declaring a patch release for @likec4/core, noting a crash fix for views using manual layout in dev mode.
Manual Layout Guard
packages/core/src/model/view/LikeC4ViewModel.ts
Added an early-return in the $manual getter: if this.#view._layout === 'manual' return this.#view to avoid re-running applyManualLayout.
E2E Test & Ignore Rules
e2e/.gitignore, e2e/tests/manual-layout-views.spec.ts
Unignored the new Playwright spec and added a test that loads an interactive view route, waits for the canvas, and asserts the error-boundary text is not visible (verifies no crash).

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related issues

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: fixing a crash by skipping manual layout re-application when it's already been applied.
Description check ✅ Passed The PR description is comprehensive and follows the template checklist, covering summary, root cause, fix, before/after, test, and file changes with issue closure reference.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/manual-layout-crash

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
packages/core/src/manual-layout/applyManualLayout.ts (1)

268-272: Move the manual fast-path before invariant checks

Line 265-267 invariants still run before the new manual short-circuit. If snapshot is stale/mismatched, this path can still throw even though the function can safely skip re-application for already-manual input.

Suggested adjustment
 export function applyManualLayout<
   V extends LayoutedView,
 >(
   autoLayouted: V,
   snapshot: ViewManualLayoutSnapshot,
 ): V {
+  if (autoLayouted._layout === 'manual') {
+    return autoLayouted
+  }
+
   invariant(autoLayouted.id === snapshot.id, 'applyManualLayout: view ids do not match')
   invariant(autoLayouted._stage === 'layouted', 'applyManualLayout: expected layouted view')
   invariant(snapshot._stage === 'layouted', 'applyManualLayout: expected layouted snapshot')
-  // If the view already has manual layout applied, return it as-is.
-  // This can happen when the Vite client receives pre-processed data (`#2882`).
-  if (autoLayouted._layout === 'manual') {
-    return autoLayouted
-  }

As per coding guidelines: “When changes relate to views (types or models), update View-drifts detection/auto-applying in src/manual-layout accordingly. If unsure what leads to layout drifts or can be auto-applied, ask for confirmation.”

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/src/manual-layout/applyManualLayout.ts` around lines 268 - 272,
The manual-layout fast-path should be moved before any invariant/snapshot
validation so we don't throw on stale/mismatched snapshot for already-manual
inputs; in applyManualLayout (look for autoLayouted and its _layout === 'manual'
check) relocate that short-circuit to run before the snapshot/invariant checks
that reference snapshot, and ensure you still run any necessary view-drifts
detection/auto-applying updates in src/manual-layout per the coding guidelines.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/core/src/manual-layout/applyManualLayout.ts`:
- Around line 268-272: The manual-layout fast-path should be moved before any
invariant/snapshot validation so we don't throw on stale/mismatched snapshot for
already-manual inputs; in applyManualLayout (look for autoLayouted and its
_layout === 'manual' check) relocate that short-circuit to run before the
snapshot/invariant checks that reference snapshot, and ensure you still run any
necessary view-drifts detection/auto-applying updates in src/manual-layout per
the coding guidelines.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7a5bcfb4-d3c6-42e2-be6d-c79a89dc7029

📥 Commits

Reviewing files that changed from the base of the PR and between e98d9f4 and 4bf6b36.

📒 Files selected for processing (2)
  • .changeset/fix-manual-layout-crash.md
  • packages/core/src/manual-layout/applyManualLayout.ts

@ckeller42

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@ckeller42 ckeller42 force-pushed the fix/manual-layout-crash branch from 4bf6b36 to 4be345b Compare April 11, 2026 20:59
@coderabbitai

coderabbitai Bot commented Apr 11, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@ckeller42 ckeller42 force-pushed the fix/manual-layout-crash branch from 4be345b to 97d4564 Compare April 11, 2026 21:20
@ckeller42

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Apr 11, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@ckeller42 ckeller42 force-pushed the fix/manual-layout-crash branch from 97d4564 to eafe583 Compare April 11, 2026 21:54
@ckeller42

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Apr 11, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

#2882)

When the Vite dev server client receives a view with _layout already set
to 'manual', LikeC4ViewModel.$manual would call applyManualLayout on
already-processed data, crashing with an invariant violation.

Moved the guard to $manual getter in LikeC4ViewModel where the data-flow
context is understood: if this.#view already has _layout: 'manual', return
it directly (it has current data + manual positions). The applyManualLayout
invariant is preserved — it correctly rejects double-application as a
contract violation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@ckeller42 ckeller42 force-pushed the fix/manual-layout-crash branch from eafe583 to 31ab78e Compare April 11, 2026 22:22
@ckeller42

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Apr 11, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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.

bug: views with manual layout crash on interactive view route (applyManualLayout invariant)

2 participants