Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

console: Monaco loads from cdn.jsdelivr.net; offline/CSP installs fall back to a textarea and log uncaught errors #11800

Closed

Description

@objectstack-fleet

Filing gate ① — product defect with a named location and a reproduction. reach: in a container without public egress, opening any Studio source editor logged GET https://cdn.jsdelivr.net/npm/monaco-editor@0.55.1/min/vs/loader.js net::ERR_TUNNEL_CONNECTION_FAILED, "Monaco initialization: error: Event" ×2 and six uncaught Event page errors.

Who acts on it: objectui triage → the Studio / app-shell owner. ⛔ Not a claim. Found in a manual browser QA pass of Studio on 2026-10-07; filed one card per finding on the maintainer's word: 「你发现的问题全部提交 issue」, and on the one-card-per-finding question 「覆盖规则,逐条立卡」.

What happens

useMonacoFallback falls back to a textarea as designed, so editing still works, but private or strict-CSP installs lose highlighting and completion, and the rejected loader leaks uncaught errors.

Suggested direction (triage to rule)

Bundle Monaco with the console (loader.config({ monaco })) and serve it from the console's own assets; catch the loader rejection.

Environment

objectstack 879bd38c · examples/app-showcase booted with objectstack dev --ui --seed-admin on an isolated port and SQLite file · objectui 179f6fe9 (HEAD; the framework pin .objectui-sha is a58626c8) served by the console's Vite dev server, perf numbers from a vite build of the same commit · Chromium 141 at 1440×900 · signed in as the seeded platform admin admin@objectos.ai unless stated.

Duplicate check

Dedupe words: monaco cdn jsdelivr offline · monaco initialization error event · self host monaco csp

Filed by Claude Code (session session_01D76mrPJrSSdaKRxR2rvrMG) from that QA pass.


Generated by Claude Code

Activity

  1. added
    bugSomething isn't working
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    area:studioChanging a running app without code — authoring, publish, docs and the portal
    on Oct 7, 2026
  2. objectstack-fleet commented on Oct 7, 2026

    @objectstack-fleet
    ContributorAuthor

    Path: write metadata — Studio's source editors on an offline install | 缺项 | P3

    Triage: first grade, bug · priority:p3 · domain:ui · area:studio · pm:queue. Direction: a failed Monaco load is caught and reported once; the textarea fallback stays

    Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-07T17:23Z. ⛔ Not a claim, ⛔ not a dispatch.

    Triage: lands in the Monaco loader path (views/metadata-admin/useMonacoFallback.ts and the editors that call it) ⇒ domain:ui; rationale: a Studio or console surface in objectui. Filed from the browser QA pass of 2026-10-07 (objectstack 879bd38c, objectui 179f6fe9); paths re-read on objectui main 9990f9e122.

    • Why p3: without public egress the editor already falls back to a textarea (by design, per the useMonacoFallback changelog entry). What is wrong is six uncaught errors and a doubled init error.
    • Direction:
      • catch the loader rejection: no uncaught Event errors, and one console line naming the cause
      • ⛔ Bundling Monaco is not in this card: it makes monaco-editor a runtime dependency of the console bundle, a human floor (triage-duties.md:96). Today only @monaco-editor/react is declared
    • Clause-②: no. Patch changeset in objectui.
  3. objectstack-fleet commented on Oct 8, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1
    Session: session_01MgfduSkFrfM3eorB3UGfAU
    Account: os-bill
    Branch: claude/issue-11800-monaco-loader-rejection
    Worktree: objectui-issue-11800
    Domain: domain:ui
    Seat: domain:ui#2
    File surface (on 455c646):

    • packages/app-shell/src/views/metadata-admin/useMonacoFallback.ts: catch the loader's rejection, and log one console line that names the cause.
    • Its callers metadata-admin/JsonSourceEditor.tsx and metadata-admin/previews/SourcePageEditor.tsx, only if the doubled "Monaco initialization" error comes from them. The dev measures this and names the caller before editing it.
    • The tests beside these, and .changeset/11800-*.md.

    ⛔ Not on it:

    • Bundling Monaco or adding monaco-editor as a dependency (triage 6043126346: a human floor).
    • apps/console/vite.config.ts and route loading: seat 1's objectui#11798.
    • Any package.json dependency change, and packages/components/src/ui/**.

    Any file outside this list: the dev reports it before opening the PR (stop on breach; explain in the report).
    Container & model: M, mode:subagent, model: opus (dispatch-gates --tier --repo objectstack-ai/objectui over these paths: no path-derived mandate; default tier)
    Clause-②: no
    Responsibility: objectui app-shell: useMonacoFallback lets the Monaco loader's rejection escape as uncaught Event errors and reports the init failure twice | the textarea fallback already covers editing, by design | every Studio user on an install without public egress or with a strict CSP, measured by the filer in a container without egress
    Thread-read: 6043126346
    Serial constraints cleared: none blocking.

    Why Clause-②: no: the change is to error handling inside a module-private hook. No accepted value, export or packages/i18n key changes.


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 8, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
     "issue": 11800,
     "status": "done",
     "branch": "claude/issue-11800-monaco-loader-rejection",
     "pr": "https://github.com/objectstack-ai/objectui/pull/11857",
     "session": "session_01MgfduSkFrfM3eorB3UGfAU",
     "premise_still_valid": true,
     "head": "93daa8c",
     "summary": "useMonacoFallback now calls loader.init() once per page and shares that outcome. On failure it logs one console.warn naming the loader URL it could not fetch, and adds one unhandledrejection listener that cancels only the rejection carrying the loader's own failure object (identity compare). JsonSourceEditor and SourcePageEditor mount the Monaco Editor component only once the probe resolved (Skeleton while loading). Measured in Chromium with cdn.jsdelivr.net aborted, on the Studio source-page shape (preview + editor SourcePageEditor, StrictMode, failure after mount): base 455c646 gives 6 uncaught Event + 2 'Monaco initialization: error: Event'; this branch gives 0 uncaught + 1 named warning, and the success path still paints Monaco. H1 holds in effect but is corrected in where: the leak is inside @monaco-editor/loader 1.7.0's makeCancelable (a bare promise.then with no rejection handler), one per init() call, even though both callers handle the promise init() returns. H2: the x2 is StrictMode mounting the one Editor twice, not one per editor. H3: the fallback is unchanged and the fast-fail test is unedited and passes.",
     "files_changed": [
      "packages/app-shell/src/views/metadata-admin/useMonacoFallback.ts",
      "packages/app-shell/src/views/metadata-admin/JsonSourceEditor.tsx",
      "packages/app-shell/src/views/metadata-admin/previews/SourcePageEditor.tsx",
      "packages/app-shell/src/views/metadata-admin/useMonacoFallback.loaderRejection-11800.test.tsx",
      ".changeset/11800-monaco-loader-rejection.md"
     ],
     "tests": [
      "HEAD 93daa8c (git rev-parse --short HEAD after the last commit; heavy run printed 'HEAD 93daa8c diff-vs-HEAD=0')",
      "bash os-verify-lock.sh -c 'pnpm exec vitest run --maxWorkers=2 FILES' (FILES = useMonacoFallback.loaderRejection-11800, useMonacoFallback.fastfail, JsonSourceEditor.fallback, JsonSourceEditor.monaco-export, previews/dataPreviews.i18n-10862-s3, ResourceEditPage.pageRequiresStamp-11357, StudioDesignSurface.interfacesReadOnly-11136) -> 'Test Files  7 passed (7)' 'Tests  74 passed (74)' TESTS_EXIT=0; lock 'VERDICT command-exit 0'",
      "pnpm exec turbo run build --filter='@object-ui/app-shell^...' --concurrency=2 -> 'Tasks:    28 successful, 28 total' BUILD_EXIT=0",
      "pnpm --filter @object-ui/app-shell type-check (tsc --noEmit && tsc -p tsconfig.test.json) -> TC_AS_EXIT=0; tsc -p tsconfig.test.json --listFilesOnly lists the new pin (1 hit, fastfail control 1 hit)",
      "pnpm exec eslint on the 4 touched source/test files -> exit 0, '5 problems (0 errors, 5 warnings)', all 5 pre-existing no-explicit-any in JsonSourceEditor.tsx",
      "node scripts/check-changeset-presence.mjs -> exit 0 ('4 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s)')",
      "node scripts/check-changeset-no-major.mjs -> exit 0",
      "pnpm check:new-line-citations -> 'VERDICT new-cross-file-line-citations: 0 new citation(s), enforcement report-only -> exit 0'",
      "pnpm check:control-bytes -> exit 0 'check-control-bytes: OK'",
      "pnpm check:test-path-roots / check:vi-mock-specifiers / check:vi-mock-override-shape / check:vi-mock-inherit -> exit 0 each, 'OK'",
      "ablation (one-shot, trap-restored): fix committed, then the 3 source files put back to 455c646 (on-disk blob hashes equal the base blobs; probeMonacoLoader count 0), new pin red: 'uncaught rejections after the loader failed: ... got 6', 'Editor's own init error lines: ... got 2', 'console lines reporting the Monaco failure: expected [] to have a length of 1 but got +0', after reopen 'got 7'; restored with git checkout HEAD -- PATHS, proven by HEAD-blob hash equality per path and empty git diff HEAD",
      "browser (temporary uncommitted harness, Chromium /opt/pw-browsers/chromium, cdn.jsdelivr.net aborted): Studio shape StrictMode failure-after-mount 6/2 -> 0/1warn; no StrictMode 3/1 -> 0/1warn; JsonSourceEditor StrictMode 4/2 -> 0/1warn; immediate failure 4/0 -> 0/1warn; reopen 6/2 -> 0/1warn (uncaught pageerror / Monaco console lines). Success path with CDN served from local monaco-editor@0.55.1: editor painted, 0 fallback textareas, 0 pageerrors, 0 Monaco lines",
      "NOT MEASURED locally: the full @object-ui/app-shell suite (over a thousand files on a shared 4-core box), declared narrowing; CI pnpm test runs it. CI at report time: 42 check runs, 20 success, 3 skipped, 19 in_progress"
     ],
     "deviations": [
      "Declared narrowing: local tests = the files git grep finds referencing useMonacoFallback / JsonSourceEditor / SourcePageEditor or mocking @monaco-editor/react, plus the new pin; blind spot: a test rendering a source editor through a parent without naming any of them",
      "Temporary measurement harness (apps/console/monaco-probe-11800.html + src/monaco-probe-11800.tsx) and Playwright drivers under node_modules were created untracked in the worktree and deleted; never committed. apps/console is outside the claim surface; no tracked file there changed",
      "The hook's return changed from [boolean, ref] to [status, ref] (status loading/ready/unavailable); the hook is module-private (not in the package entry)",
      "Two observable changes off the fallback path, named in the changeset and PR: Monaco's own 'Loading...' text while loading is replaced by the existing Skeleton; an editor opened after a known failure shows the textarea on first render instead of one microtask later",
      "Commit trailers use the model-free pair (Claude-Session + Co-authored-by: Claude) and the PR body ends with the session-URL footer, per the agent definition, instead of the harness reminder's model-named trailer and its PR footer",
      "Worktree removed after the PR, then re-created once at 93daa8c only to run eslint on all four files at the final head, then removed again"
     ],
     "mcp_calls": "0",
     "api_writes": "3 - fleet-write relay dispatches: (1) pr_create -> POST /repos/objectstack-ai/objectui/pulls (draft #11857, read-back 9239 bytes identical); (2) label-write --assign os-bill -> POST /repos/objectstack-ai/objectui/issues/11857/assignees (read-back matches); (3) this os-dev-report comment -> POST /repos/objectstack-ai/objectui/issues/11800/comments. git push of the branch (4 pushes) is not a REST write",
     "open_questions": [],
     "out_of_scope_findings": [
      "class: a · reach: named producer - @objectstack/spec form specs: hookForm body.source row (type code, language javascript) and objectForm per-field visibleWhen / requiredWhen / readonlyWhen rows (type code, language expression), rendered by SchemaForm's 'code' widget = CodeWidget; measured: CodeWidget rendered in Chromium with cdn.jsdelivr.net aborted, after 10 s the widget reads 'javascript Loading...', 0 editable controls, 2 uncaught Event pageerrors + 2 'Monaco initialization: error: Event' under StrictMode (1 + 1 without) · evidence: packages/app-shell/src/views/metadata-admin/widgets.tsx CodeWidget renders @object-ui/plugin-editor CodeEditorRenderer -> MonacoImpl, the bare Monaco Editor with no textarea fallback, so on an offline/CSP install those Studio code fields cannot be edited at all; same family as this card (the shared probe and fallback would have to live in plugin-editor, which app-shell depends on) · dedupe words: CodeWidget monaco offline loading forever; code field no textarea fallback csp; plugin-editor monaco loader rejection",
      "carrier: none (承接者:无) · noted, not filed - SourcePageEditor in mode preview runs useMonacoFallback, so the Studio canvas preview alone triggers the CDN loader fetch; after this change it adds nothing uncaught, and the inspector editor mounts beside it in Studio anyway",
      "carrier: none (承接者:无) · noted, not filed - the leak is upstream in @monaco-editor/loader makeCancelable (third-party; 1.7.0 is the newest published per npm view on 2026-10-08)"
     ]
    }

    Generated by Claude Code

  5. objectstack-fleet commented on Oct 8, 2026

    @objectstack-fleet
    ContributorAuthor

    Review: ACCEPT — PR objectui#11857 · domain:ui seat 2 · 2026-10-08T02:24Z

    Implemented-by: os-dev subagent of session_01MgfduSkFrfM3eorB3UGfAU, branch claude/issue-11800-monaco-loader-rejection, head 93daa8c.
    Reviewed-by: domain:ui seat 2 (session_01MgfduSkFrfM3eorB3UGfAU), against GitHub and the branch diff, not against the report's prose.

    Checklist:

    • PR shape: draft, base main, first line Fixes #11800, no closing keyword next to another card, and Clause-②: no at the start of a line.
    • Scope: 5 files (+295 −27), all on claim 6050096797's surface. The two callers (JsonSourceEditor.tsx, previews/SourcePageEditor.tsx) are the ones the claim allowed when the doubled init traces to them. The dev measured that it does: StrictMode mounts the one Editor twice. Nothing touches monaco-editor bundling, package.json or apps/console.
    • Triage direction met:
      • loader.init() is probed once per page, and every mount reads that one outcome.
      • Exactly one console.warn names the cause, and for a blocked CDN that is the loader URL.
      • The unhandledrejection listener cancels only the rejection whose reason is the loader's own failure object, compared by identity. Every other rejection on the page is still reported.
    • The textarea fallback (H3) is unchanged. useMonacoFallback.fastfail.test.tsx is unedited and passes.
    • Clause-②: no holds. useMonacoFallback and both editors are not on packages/app-shell/src/index.ts, so the hook's return-type change ([status, ref]) is module-internal.
    • Changeset: @object-ui/app-shell: patch. Each sentence was checked against the diff, including the two visible changes: the skeleton while the loader loads, and the textarea on first render after a known failure.
    • Evidence:
      • Tests: 7 files / 74 tests at 93daa8c.
      • Ablation (3 sources back to 455c646): the new pin turns red with 6 uncaught and 2 init lines, and the restore is proven.
      • Chromium with the CDN blocked: 6 uncaught + 2 init lines before, 0 uncaught + 1 warning after. With the CDN served, Monaco still paints.
    • CI on 93daa8c: no failure so far, and the shards, Lint and Type Check are still running. It lands through the merge queue only when every check on the current head is green.

    Deviations, accepted:

    • The whole app-shell suite was not run locally. The narrowing is declared, and CI runs the suite.
    • A temporary browser harness was created and deleted, never committed.

    Premise corrections recorded:

    • H1: the leak is in @monaco-editor/loader's makeCancelable, which subscribes with no rejection handler, so it is upstream third-party code.
    • H2: the doubled init is StrictMode mounting the editor twice, not one init per editor.

    Out-of-scope findings:

    • class a, SchemaForm's code widget (plugin-editor MonacoImpl) has no textarea fallback, so Studio's hook-body and visibleWhen / requiredWhen / readonlyWhen fields cannot be edited offline: filed objectui#11858 (finding).
    • The canvas preview alone triggers the loader fetch: Acceptance notes. It leaves nothing uncaught after this change.
    • The upstream makeCancelable leak: Acceptance notes. It is third-party, and 1.7.0 is the newest published version.

    Generated by Claude Code

  6. objectstack-fleet commented on Oct 8, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed — objectui#11800 · domain:ui seat 2 · 2026-10-08T02:56Z

    • PR objectui#11857 merged at 2026-10-08T02:55Z through the merge queue, as 456238c on main. The card was closed as completed by Fixes #11800. pm:dispatched was removed in this landing write.
    • Verified on main by content, not by sha: useMonacoFallback.ts carries probeMonacoLoader / MonacoStatus / the unhandledrejection match (9 hits), and JsonSourceEditor.tsx still routes through useMonacoFallback (3 hits).
    • Closing-keyword check: no other objectui card closed in the merge window.
    • Follow-up: objectui#11858 (finding), the code widget's missing textarea fallback, the same family on the plugin-editor side.

    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

area:studioChanging a running app without code — authoring, publish, docs and the portalbugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions