github →

Issue #21095

App-installed FIELDS widget: configuration.viewId stored as null after manifest sync

abandoned
bug●● medium90% confidencesonarly:hightype: bug

Bug Description

A Twenty SDK app declares a page layout with a FIELDS widget whose configuration.viewId references a view's universalIdentifier. After app:dev sync, the widget is stored in the database with a null viewId. Querying core."pageLayoutWidget" shows:

{"viewId": null, "configurationType": "FIELDS"}

Confirmed across two separate syncs. The built manifest.json has the correct view identifier, and the views themselves persist with real ids — only the FIELDS-widget viewId comes back null. As a result the widget renders every field ungrouped instead of the curated view, so an app cannot drive grouped field columns this way.

For contrast: a FRONT_COMPONENT widget's frontComponentId in the same app resolves correctly, and the native (server-seeded) Home-tab FIELDS widget has a real viewId. The issue is specific to FIELDS-widget viewId resolved via app manifest sync.

Observed on a self-hosted v2.8.3 instance.

Expected behavior

After sync, the FIELDS widget's configuration.viewId should hold the resolved id of the referenced view (the same way a FRONT_COMPONENT widget's frontComponentId does), so the widget renders the curated field groups from that view.

Technical inputs

Reporting as a new contributor (not a developer); I found this with Claude Code and traced the source against a clone that may be behind latest main, so paths may differ — please verify on current main, I could easily be wrong on the internals.

  • It looks like the FIELDS-widget viewId may not be resolved as a serialized relation during app sync the way frontComponentId is. In the types I saw, FrontComponentConfiguration.frontComponentId is marked as a SerializedRelation, whereas FieldsConfiguration.viewId is typed as a plain string — which could explain why one resolves and the other stores null.
  • The built manifest.json was correct (viewId = the view's universalIdentifier), so it appears to be server-side resolution during sync, not a manifest authoring problem.
  • Repro: define a defineView with field groups + a definePageLayout FIELDS widget whose configuration.viewId is that view's universalIdentifier -> app:dev sync -> query core."pageLayoutWidget" -> viewId is null.
  • Workaround we used: render the grouped columns with a FRONT_COMPONENT instead (its frontComponentId resolves fine).
What happened

Agent made no changes

The agent reviewed the issue and the repo but decided not to commit anything. Common causes: the issue is already addressed on the branch, the description is ambiguous, or the agent could not locate the files to edit.

Suggested next step Open the PR thread below and leave a comment with more specific guidance (file paths, expected behaviour, examples). Gitgot will re-run the agent automatically with the comment as steering.

Technical details ↓
agent ran but produced no changes (exit 0)

--- agent stdout tail ---
[turn 1] read_file → 194 lines
[turn 1] read_file → 493 lines
[turn 2] grep → 5 matches
[turn 2] grep → 0 matches
[turn 3] read_file → 94 lines
[turn 3] grep → 1 matches
[turn 4] read_file → 382 lines
[turn 4] grep → 6 matches
[turn 5] grep → 2 matches
[turn 5] grep → 30 matches
[turn 6] grep → 1 matches
[turn 6] grep → 30 matches
[turn 7] bash_exec → exit=0 stdout_bytes=3838 stderr_bytes=37
[turn 7] bash_exec → exit=0 stdout_bytes=2506 stderr_bytes=0
[turn 8] read_file → 238 lines
[turn 9] read_file → 321 lines
[turn 10] read_file → 622 lines
[turn 11] read_file → 44 lines
[turn 12] grep → 31 matches
[turn 12] grep → 41 matches
[turn 13] read_file → 366 lines
[turn 14] grep → 1 matches
[turn 15] grep → 3 matches
[turn 16] read_file → 34 lines
[turn 17] read_file → 7 lines
[turn 18] read_file → 39 lines
[turn 19] read_file → 43 lines
[turn 19] read_file → 17 lines
[turn 20] read_file → 59 lines
[turn 21] grep → 12 matches
[turn 22] grep → 30 matches
[turn 23] read_file → 60 lines
[turn 24] read_file → 606 lines
[turn 25] grep → 5 matches
[turn 26] read_file → 98 lines
[turn 26] read_file → 109 lines
[turn 27] grep → 22 matches
[turn 28] read_file → 124 lines
[turn 29] read_file → 32 lines
[turn 30] read_file → 452 lines
[turn 31] read_file → 103 lines
[turn 32] read_file → 79 lines
[turn 33] read_file → 86 lines
[turn 34] read_file → 1688 lines
[turn 35] read_file → 58 lines
[turn 36] grep → 1 matches
[turn 37] read_file → 21 lines
[turn 38] read_file → 14 lines
[turn 39] read_file → 5 lines
[turn 40] read_file → 6 lines
(max turns 40 reached)

Triggering a new request for this issue creates a fresh sandbox and a fresh agent run. Most abandoned states resolve on a clean retry — but if the failure suggests a config problem (missing API key, App not installed, etc.), fix the underlying cause first.

Verification

Verification runs after the agent commits and on every push to the PR branch. Nothing has run yet.

Get the code

Drive locally

Paste this into your local coding agent (Claude Code, Cursor, etc.) to continue iterating with full repo context.

Context prompt
You are continuing work on a draft PR for twentyhq/twenty, addressing issue #21095.

Review gitgot's first-pass change on the PR branch, then:
- run the project's lint/typecheck/test commands and fix anything broken
- if the diff is wrong-headed, revert it and start fresh from the issue
- keep the change tight; do not refactor unrelated code