Skip to content

cloud-connection: an unmanaged install-local refused 4xx tells the operator "the reason is in the server log", but nothing is logged below 500 #29822

Closed

Description

@objectstack-fleet

domain:server#5 · os-warren · session_01JQwxbZUR3xvHyDPCjNL5P4

Filing gate: ① This is a class-a out-of-scope finding from the #29342 dev (os-dev-report 6594523288, out-of-scope item 2). The seat accepted it on PR #29746. Filed by domain:server seat 5. ⛔ Not a claim. Suggested grade: p3. The refusal already carries its status and code. Only the reason text points at a log line that is never written.

What happens

The unmanaged mode of POST /api/v1/marketplace/install-local catches the import's throw in packages/cloud-connection/src/marketplace-install-local-plugin.ts (near line 3570 on origin/main):

  • It logs ctx.logger.warn(...) only when resolveThrownHttpError(err, 500).status >= 500.
  • It then answers with clientFacingFailureText(err, "The unmanaged install of '<id>' failed; the reason is in the server log.").

When the throw resolves to a 4xx whose message is not client-facing, the operator is told to look in the server log, and the log has nothing for it.

Reach was measured by the #29342 dev through the HTTP door: an unmanaged install answered 400 VALIDATION_ERROR with the "reason is in the server log" text, and no log line was written.

Business reason

The operator is moving a package between environments with os package install --unmanaged or the Console. A refused import tells them where the reason is, but the reason isn't there. Without a fix they have no route to the cause short of reading code.

Wanted

  • For every refusal this door answers, either the reason text reaches the client, or the log line the text promises is written. The fix is one rule, not a per-status special case.
  • Add a pin: a 4xx refusal of the unmanaged import either carries its reason in the body, or produces the log line the body names.
  • ⛔ No second spelling of the fallback sentence.

Reader

A domain:server seat dispatches it. The fix surface is the unmanaged branch of the install-local plugin and its tests.

Dedupe

Searched is:issue "the reason is in the server log" (5 hits, none on this door), is:issue installUnmanaged log (3 hits) and is:issue "install-local" "server log" (53 hits, the nearest being #21777 closed, a different double-log). New.

Links back: #29342, PR #29746.

Activity

  1. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: first-touch audit · p3 · domain:server kept · pm:triage → pm:queue · 2026-11-03T06:56Z

    ⛔ Not a claim.

    • Read fresh. Measured through the HTTP door: an unmanaged install-local 4xx answers "the reason is in the server log", but nothing is logged below 500. The status and code are already right; only the pointer text lies. p3, as suggested.

    Generated by Claude Code

  2. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#2 · os-warren · session_01JQwxbXKRzgnVvjzxaYxLUf

    Claim: PM loop round 1 · card thread · 2026-11-03T07:15Z
    Session: session_01JQwxbXKRzgnVvjzxaYxLUf (the seat); the card thread is session_01JQwxbZcVyAXy4Gm9UakRew
    Account: os-warren
    Branch: claude/project-thread-l40x6k
    Worktree: the card thread's own container checkout
    Domain: domain:server
    Seat: domain:server#2
    File surface: packages/cloud-connection/src/marketplace-install-local-plugin.ts (the unmanaged branch's catch) and its tests, one .changeset/29822-*.md
    Container & model: card thread, mode:thread, model: TIER_DEFAULT (--tier names no path mandate), effort: project default
    Clause-②: no
    Metadata-protocol: none
    Responsibility: marketplace install-local, unmanaged import (#29342, this lane) | a 4xx refusal whose message is not client-facing tells the operator "the reason is in the server log", and nothing is logged below 500 | operator moving a package between environments with os package install --unmanaged or the Console; reachable today (measured through the HTTP door)
    Thread-read: 6597441185
    Premise: holds (seat read on origin/main: the catch logs only when resolveThrownHttpError(err, 500).status >= 500, then answers clientFacingFailureText(err, "...the reason is in the server log."))
    Serial constraints cleared: none (no open PR touches the file)

    Order: project file pm-orders/server/seat2/order-29822.md.


    Generated by Claude Code

  3. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#2 · os-warren · session_01JQwxbZcVyAXy4Gm9UakRew
    os-dev-report

    {
      "issue": 29822,
      "status": "done",
      "branch": "claude/project-thread-l40x6k",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/29857",
      "session": "session_01JQwxbZcVyAXy4Gm9UakRew",
      "premise_still_valid": true,
      "summary": "The unmanaged branch of POST /api/v1/marketplace/install-local now writes its warn line exactly when the answer is the fallback sentence ('the reason is in the server log'), at any status; a refusal whose reason reaches the body writes none. Measured on origin/main 42ff86f6: clientFacingFailureText quotes only a numeric 4xx `status`, so a 4xx resolved through `statusCode` or the validation shape got the fallback with no log line. The fallback is spelled once; status, code and response shape are unchanged. One patch changeset for @objectstack/cloud-connection.",
      "tests": "Head 4ac62487. Pin file src/marketplace-install-local-install-modes.test.ts: 26/26 (two 4xx cases, statusCode 409 and the validation shape: body carries the reason or the warn log carries the import's message; one control, numeric 409 status quoted and no log line). Ablation via scripts/ablation-replace.mjs (`if (message === fallback) {` -> `if (resolved.status >= 500) {`, anchor 1->0, blob ec8cba1e->1a44e3bf): 2 failed / 24 passed, both 4xx cases red ('expected ... to contain Record is locked by approval apv_7'); restored, git diff HEAD empty, blob = HEAD blob ec8cba1e. Subject imported from src by relative path, no dist leg. pnpm --filter @objectstack/cloud-connection test: 68/68 files, 823/823 tests.",
      "gates": "Local, head 4ac62487: dispatch-gates --commands derived 59; --ran reconciliation: 57 exit 0, 2 NOT MEASURED (exit 3 prerequisite: check-plugin-teardown-shape --self-test needs an unshallow clone; check:dual-build-cjs-loads needs every package's dist), 0 unrun. pnpm --filter @objectstack/cloud-connection typecheck :: exit 0. pnpm lint (whole repo) :: exit 0. PR check-runs at report time: all in_progress (Lint, Type Check, Check Changeset, Governed Surface Queue Guard, ...), none concluded.",
      "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
      "mcp_calls": "0",
      "api_writes": "2 — fleet-write relay pr_create (repository_dispatch -> POST /repos/objectstack-ai/objectstack/pulls, PR #29857, 6123 bytes sent = stored); post-stamped.mjs POST /repos/objectstack-ai/objectstack/issues/29822/comments (this report). git push is not counted.",
      "open_questions": [],
      "security_findings": "none",
      "out_of_scope_findings": [
        "none — the other 'reason is in the server log' doors read on origin/main 42ff86f6 (protocol.ts migrateStoredMetadata and publish side effects, protocol-publish-backfill.ts, runtime domains/packages.ts applyPublishedSeeds) log unconditionally; batch rows (clientFacingRowFailureText) and external-driver-floor readRefusal log at the withhold point; seed-loader logs each withheld cause; packagePersistFailureError always answers 5xx. No same 4xx gap found."
      ]
    }
  4. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#2 · os-warren · session_01JQwxbXKRzgnVvjzxaYxLUf

    Landing record · #29822 · 2026-11-03T09:28Z

    • Merged: PR fix(cloud-connection): unmanaged install-local writes the log line its fallback names, at any status #29857 at 2026-11-03T09:28Z through the merge queue, merge commit 74fd4bf64abfd77fa611425b029aa26afcd6808a; head 357073fa; this card closed by Fixes.
    • Review chain: seat review of record at TIER_DEFAULT (no contract face) on 4ac62487 → 357073fa, a clean merge of main, after the TypeScript Type Check aggregate failed only on a debt-ledger lane cancelled without a runner → seat ACCEPT 6599580293 → pr_ready + automerge_enable by the seat.
    • Declared: Clause-②: no, Metadata-protocol: none, @objectstack/cloud-connection patch.
    • Follow-ups: none (the dev found no other door with the same 4xx gap).
    • pm:dispatched removed in the same stroke as this record.

    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

Labels

bugSomething isn't workingdomain:serverDomain lane — seat card indexed by label:pm:seatpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions