Skip to content

A publish failure's error string inlines the same validation prose that issues[] already carries, so every console renders each finding twice #10524

Closed

Description

@os-support-ai

Filed from objectstack-ai/objectui#5418 (Studio dogfood, 17.1.0). Filed here, not in objectui, because the fix is producer-side: de-duplicating in the consumer is the alias-tolerance shape Prime Directive #12 forbids, so objectui deliberately did not touch it.

Measured

The publish-drafts response's failed[] entries carry both:

  • error — a summary string that already contains the rendered issue text, and
  • issues[] — the same findings, structured ({ path, message }).

objectui's formatPublishFailures renders ${type}/${name}: ${error} and then one • path — message line per issue, which is the right thing to do with that contract — it is what turns an opaque banner into a field-anchored list. The result on the card's walk was the same sentence twice:

object/crmext_visit: [invalid_metadata] object/crmext_visit failed author-time validation:
objects[71].sharingModel: [security-owd-unset] custom object "crmext_visit" declares no
sharingModel (OWD). The runtime fails CLOSED to 'private' (ADR-0090 D1), but the baseline
must be an authored decision, not an accident — this is the exact shape of the leave_request
incident (objectstack-ai/objectui#2348). • objects[71].sharingModel — custom object "crmext_visit" declares
no sharingModel (OWD). …

The original reporter called this out directly: "a wall of English ADR prose (the same sentence twice, once as a summary and once as a bullet)".

Why the consumer must not fix it

Every plausible client-side fix is a guess about producer text — strip the summary when issues.length > 0 (loses the summary's own framing for non-validation failures), or substring-match the issue text out of error (a parser for prose). Both are exactly the consumer tolerance that hides producer drift.

Suggested shape

error should be the headline — what failed and why, one sentence — with the per-path detail left to issues[], which is the structured channel that exists for it. Consumers that render only error (logs, CLI) keep a usable message; consumers that render both stop repeating themselves.

Confidence / what I did NOT measure

The duplication is read off the reporter's captured console output plus objectui's formatter, which I did read. I did not run a live publish against a framework build to confirm which server-side site composes error — worth confirming before choosing where the change lands.

Related

Activity

  1. added
    pm:queueReady for the PM dispatch loop
    domain:engineRetired 2026-10-22, alias of domain:server (engine surface); in-flight cards keep it until they land
    on Aug 21, 2026
  2. added theissue type on Aug 21, 2026
  3. os-zhuang commented on Aug 21, 2026

    @os-zhuang
    Contributor

    Triage: producer-side fix (the publish-drafts failed[] composer, framework side) → domain:engine, pm:queue, type Task. The consumer-side non-fix is already ruled posture (alias-tolerance forbidden), so the only landing site is where error is composed.

    Dispatch notes, premise-first: the filer did not confirm which server-side site composes error — the dev's first step is locating it (likely the metadata publish path that builds failed[] entries; verify, don't inherit). Target shape as suggested: error = one-sentence headline, per-path detail stays in issues[]. Check consumers that render only error (CLI, logs) keep a usable message — that is the acceptance criterion, not string equality with today. Relation: #10462 (open decision card on publishPackageDrafts success:false semantics) touches the same response contract — if its ruling lands first, re-read this card's shape against it; do not pre-empt that ruling here.

    Size/model suggestion: S–M, mode:subagent, opus.


    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

    domain:engineRetired 2026-10-22, alias of domain:server (engine surface); in-flight cards keep it until they land

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions