Skip to content

Address fields render as raw JSON on the record detail page #664

Description

@xuyushun441-sys

Found while browser-verifying the ObjectStack 17.0.0-rc.2 upgrade (#663). Filing it separately because it is not caused by that upgrade — see the attribution below.

What happens

On an account detail page, the billing_address field renders its stored value verbatim as JSON instead of as a formatted address:

BILLING ADDRESS
{"street":"500 Howard Street, Suite 400","city":"San Francisco","state":"CA","postalCode":"94105","country":"US"}

The neighbouring BILLING COUNTRY (a plain text field) renders normally as US, so the page itself is fine — it is the address field type's detail-page renderer that has no formatter and falls back to stringifying the object.

Why it matters

crm_account.billing_address is authored with Field.address(...), i.e. a structured postal address — the type exists precisely so the platform knows the value has parts. A business user reading an account record sees a JSON blob where they expect a mailing address, and it is the widest field on the page. The same field type is used on other objects, so any record carrying an address has the same presentation.

Note this is presentation only: the stored value is correct and well-formed, and the API returns it correctly.

Reproduce

  1. pnpm demo:reset then pnpm dev
  2. Sign in as the dev admin (admin@objectos.ai / admin123)
  3. Open any seeded account with a billing address, e.g. /_console/apps/app.objectstack.hotcrm/crm_account/record/<id> → Contact Information group

Not caused by the 17.0.0-rc.2 upgrade

Measured rather than assumed. I booted an origin/main worktree (still on 17.0.0-rc.1) on port 4002 alongside the rc.2 server on 4001 and read the same field on the same seeded account through the same Chromium session:

build rendered text
17.0.0-rc.1 (origin/main) {"street":"500 Howard Street, Suite 400","city":"San Francisco","state":"CA","postalCode":"94105","country":"US"}
17.0.0-rc.2 (#663) byte-identical

So this predates the upgrade and is longstanding.

Where the fix likely belongs

Probably not in this repo: the detail-page field renderer is Console (objectui) territory, and HotCRM's side (Field.address() on crm_account.billing_address / shipping_address) looks correctly authored. Worth confirming which layer owns the address formatter before deciding whether this is a HotCRM issue at all or should move upstream — if the renderer is missing entirely, the upstream fix benefits every app, and a HotCRM-local workaround (splitting the address into flat text fields) would be the wrong trade.

Activity

  1. added
    upstream:objectstackBlocked on / caused by the ObjectStack platform — tracked upstream
    on Aug 4, 2026
  2. os-zhuang commented on Aug 4, 2026

    @os-zhuang
    Contributor

    分诊(PM 循环第 1 轮扫检,会话 session_01Rvtsew6XgsSjxVa59HRPRK):落地层不在本仓,加 upstream:objectstack,不入 pm:queue。

    核验:objectstack 仓的 packages/console 只是发布包装(无源码),记录详情页的字段渲染器在 Console 前端(objectui)。hotcrm 侧 Field.address() 的作者姿态正确(issue 正文的双版本对照也证明了与 rc.2 升级无关),本仓没有可改动的代码 —— issue 正文的判断(「HotCRM-local workaround 拆平字段是错误的取舍」)采纳:不做本地绕过。

    待办(PM 跟进):在上游归档「address 字段类型缺 detail-page 格式化器」的 issue(附本 issue 的复现与截图路径),拿到链接后回填到这里。在上游修复发版前,本 issue 保持 open 作为跟踪单。


    Generated by Claude Code

  3. os-zhuang commented on Aug 4, 2026

    @os-zhuang
    Contributor

    上游查重结果:已存在完全对应的平台 issue —— objectstack-ai/objectstack#5019(「Record detail page renders address fields as raw JSON — the display registry has a location formatter but no address one」),且已在上游 PM 队列中。无需新档。

    Blocked-by: objectstack-ai/objectstack#5019。上游修复发版并被本仓吸收后,按本 issue 的复现步骤回验并关闭。


    Generated by Claude Code

  4. yinlianghui commented on Aug 5, 2026

    @yinlianghui
    Collaborator

    [17.0-rc2验收复核] 测试组 A6 在 hotcrm@0899b4f + @objectstack 17.0.0-rc.2 全新 dev 环境实测:问题依旧存在,原样复现。

    • 客户详情页(如 seeded Vertex Analytics / Wayne Enterprises)Contact Information 分组的 BILLING ADDRESS 仍渲染原始 JSON:{"street":"600 Congress Avenue, Floor 14","city":"Austin","state":"TX","postalCode":"78701",…},为整页最宽字段;相邻 BILLING COUNTRY(text)正常显示 US。
    • 走查 17 个 crm_* 对象详情页,address 型字段仅 crm_account(billing/shipping)受影响,现象与本单描述逐字一致。
    • 表单侧不受影响:新建/编辑表单里 address 拆成 Street/City/State/ZIP/Country 子输入,正常可编辑 —— 缺的只是详情页的格式化渲染器,与本单「Console (objectui) 层缺 address formatter」的定位一致。

    补充一个同族线索:平台仓已有 open 单 objectstack#5083(AddressField 子标签硬编码英文)、objectstack#5143(AddressField ZIP 绑定 zipCode 与存储 postalCode 不一致),说明 AddressField 在 console 侧仍在补齐,详情页 formatter 缺失建议一并在平台侧跟进。


    Generated by Claude Code

  5. huangyiirene commented on Aug 11, 2026

    @huangyiirene
    Collaborator

    Re-measured on @objectstack/* 17.0.0-rc.6 during the rc.5 → rc.6 upgrade (#1059, PR #1066). The console now ships an address formatter — which is what this card concluded was missing, and it landed where the card predicted it belonged (upstream, not here).

    @objectstack/console's bundled ui-components asset carries an AddressField whose readonly branch formats the parts rather than stringifying the object:

    h = e => [e.street, e.city, [e.state, postal(e)].filter(Boolean).join(' '), e.country]
              .filter(Boolean).join(', ')
    if (readonly) { let s = h(value); return <span className="text-sm">…

    So crm_account.billing_address should now render as 500 Howard Street, Suite 400, San Francisco, CA 94105, US rather than the JSON blob. The component also normalises zipCode → postalCode, which suggests the value shape this app writes is the one it expects.

    This also settles the card's open question — "worth confirming which layer owns the address formatter before deciding whether this is a HotCRM issue at all". It is Console's, and no HotCRM-local workaround is needed. Field.address() on billing_address / shipping_address stays as authored, and the "split the address into flat text fields" trade the card flagged as wrong can stay untaken.

    Scope note — not browser-verified. This is a static read of the shipped component, not the reproduction steps in this card. Someone should do the pnpm demo:reset → pnpm dev → open a seeded account pass before closing, because a formatter existing in the bundle and the detail page actually routing an address field to it are two different claims, and this card was originally filed on precisely that gap.


    Generated by Claude Code

  6. hotlong commented on Aug 14, 2026

    @hotlong
    Contributor

    GA browser probe — NOT REPRODUCIBLE on 17.0.0 GA · closing

    This is the browser verification the rc.6 comment explicitly deferred ("a formatter existing in the bundle and the detail page actually routing an address field to it are two different claims"). Both claims now hold.

    Version — @objectstack/* 17.0.0 GA, all 50 installed packages including @objectstack/console (checked node_modules/@objectstack/console/package.json → 17.0.0, not an rc). hotcrm @ d4ddee0.

    Probe — wiped .objectstack/data, pnpm build, objectstack dev -p 4003 --seed-admin, real Chromium 141 driven by Playwright, signed in through the console UI as admin@objectos.ai, opened
    /_console/apps/app.objectstack.hotcrm/crm_account/record/JcMPk-7IMMkoHY8X — seeded Acme Corporation (ACC-000001), i.e. the exact record and the exact stored address this card was filed on:

    {"street":"500 Howard Street, Suite 400","city":"San Francisco","state":"CA","postalCode":"94105","country":"US"}

    Result — the Contact Information group renders, label-anchored from the live DOM:

    BILLING ADDRESS | 500 Howard Street, Suite 400, San Francisco, CA 94105, US
    

    Byte-for-byte the comma-joined form the rc.6 static read predicted. Neighbouring BILLING COUNTRY still renders US independently, exactly as the original report described.

    What I would have seen if the defect were still present

    Stated before running, so the green is falsifiable rather than decorative:

    check if defect still live measured on GA
    raw JSON blob ({"street" / "postalCode") anywhere in page text present absent
    exact string 500 Howard Street, Suite 400, San Francisco, CA 94105, US absent present
    record identity guard — page really rendered this record — Acme Corporation present

    The third row matters: a blank or unpopulated field would also have shown "no raw JSON", and that would have been a vacuous pass. The address is populated and formatted.

    Screenshot — 664-address-closeup-GA.png: the Contact Information card with PHONE / WEBSITE / BILLING ADDRESS / BILLING COUNTRY in one frame, BILLING ADDRESS reading 500 Howard Street, Suite 40… (clamped by column width in the visual; the full string is in the DOM text above).

    Cosmetic note, not a defect and not re-opening anything: the value is CSS-truncated to its column, so the long form shows an ellipsis. The original complaint was "widest field on the page"; it is now clamped like its neighbours.

    Fixed upstream in console, exactly where this card predicted it belonged — no HotCRM-local change was needed and the "split the address into flat text fields" trade stayed untaken. Blocked-by: objectstack-ai/objectstack#5019 is discharged. Removing pm:blocked in the same label write as this close.

    Probed under #1154 (parent #1150).


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinguiupstream:objectstackBlocked on / caused by the ObjectStack platform — tracked upstream

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions