Skip to content

Backend esm vitest#7605

Draft
SamTV12345 wants to merge 65 commits into
developfrom
backend-esm-vitest
Draft

Backend esm vitest#7605
SamTV12345 wants to merge 65 commits into
developfrom
backend-esm-vitest

Conversation

@SamTV12345
Copy link
Copy Markdown
Member

No description provided.

SamTV12345 and others added 30 commits April 26, 2026 12:15
Converted: customError, Stream, NodeVersion, checkValidRev, AbsolutePaths
(+__dirname shim), run_cmd, Cleanup, ExportHelper, padDiff, ExportTxt,
LibreOffice, UpdateCheck, ImportHtml.

Still CJS in utils/: Settings, Minify, toolbar, ExportEtherpad,
ImportEtherpad, ExportHtml. Their consumers will surface errors until
they're flipped too. ts-check: 530 -> 526 errors.
…ad, ImportEtherpad, ExportHtml, toolbar)

All 26 files in node/utils/ now ESM. Settings.ts CJS shim removed (dead code
under "type": module); plugins doing require() get .default-wrapped namespace
via Node interop, the createRequire bridge in pluginfw will preserve sync
loading once that lands. toolbar.ts's module.exports.availableButtons
self-reference replaced by a module-private toolbar const.

ts-check: 526 -> 539 errors. The +13 is from default-imports landing on
modules that still live in db/ as CJS; resolves once db/ is flipped.
Self-referential exports.X pattern replaced by a module-private `eejs` object
that's also the default export. __dirname shimmed via import.meta.url.
`require` (used by templates as args.require) preserved via createRequire.
DB.ts: wrapped mutable exports as default-exported `dbModule` so init() can
still re-bind get/set/findKeys at runtime.
AuthorManager / GroupManager / PadManager / SessionManager: exports.X -> export
const X. Internal self-references (exports.X(...)) replaced with bare X(...).
Aliases (doesAuthorExists, doesPadExists, getAuthor4Token-deprecated)
preserved.
SecurityManager / ReadOnlyManager: imports flipped to .js.
SessionStore: module.exports -> export default.
Pad: `exports.cleanText` and `exports.Pad = Pad` now `export const cleanText`
and `export { Pad }`. Internal exports.cleanText() calls -> cleanText().
API: ~40 `exports.X = ...` rewritten to `export const X = ...`.
crypto.ts: util.promisify wrappers exported as named consts.
SecretRotator: import flips, all internal refs already named.
OIDCAdapter / OAuth2Provider / OAuth2User: already ESM, just .js suffixes.
APIHandler / APIKeyHandler / SocketIORouter / ExportHandler / ImportHandler /
RestAPI: imports flipped to .js, exports.X -> export const X.
PadMessageHandler: full conversion incl. internal exports.X() callsites
(sendChatMessageToPadClients, updatePadClients, composePadChangesets) rewritten
to bare names. Default export object added so existing
`import padMessageHandler from '...'` callers keep working without changes.
Conditional require() of LibreOffice in ImportHandler/ExportHandler hoisted
to a top-level namespace import (`import * as converterModule`).
…s/* files)

Done: express.ts (incl. https/http hoisted to top-level imports, exports.server
+ exports.sessionMiddleware -> export let), i18n.ts, admin.ts, webaccess.ts
(authnFailureDelayMs preserved as export let + setter), padurlsanitize.ts,
pwa.ts, errorhandling.ts (exports.app preserved as export let), tokenTransfer.ts,
adminplugins.ts.

Still CJS in hooks/express/: adminsettings, apicalls, importexport, openapi,
socketio, specialpages, static.
…tsort to ESM, add createRequire bridge in shared.ts
…toreRevision, instance, health, fuzzImportTest

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ctor, export_list

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…y, sanitizePluginsForWire, messages

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…gression-db, lowerCasePadIds

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ebaccess, undo_clear_authorship, specialpages, socketio

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Change 'import common from' to 'import * as common from' in 20 test files
to use named imports instead of default import.

Co-authored-by: GitHub Copilot <copilot@github.com>
Replace default imports with namespace imports for modules that only export
named exports:
- PadManager.ts: export const getPad, listAllPads, etc.
- AuthorManager.ts: export const getAuthor, etc.
- ImportHtml.ts: export const setPadHTML
- ExportHtml.ts: export const getPadHTMLDocument

Changed 'import X from Y' to 'import * as X from Y' in:
- Test files (export_list, chat, messages, etc.)
- Utility files (ExportHtml, ExportTxt, ExportEtherpad, ImportEtherpad, Cleanup)
- API test files (pad, restoreRevision)

This fixes ESM module resolution errors when these modules are imported as
default exports despite only providing named exports.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Convert const X = require('Y') to import X from 'Y.js'
- Convert const {A, B} = require('Y') to import {A, B} from 'Y.js'
- Add .js extensions to relative imports
- Keep external packages without .js (e.g., 'tinycon/tinycon')
- Convert exports.X = Y to export {X}

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Convert const X = require('Y') to import X from 'Y.js'
- Convert const {A, B} = require('Y') to import {A, B} from 'Y.js'
- Add .js extensions to relative imports
- Keep external packages without .js (e.g., 'tinycon/tinycon')
- Convert exports.X = Y to export {X}

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Convert const X = require('Y') to import X from 'Y.js'
- Convert const {A, B} = require('Y') to import {A, B} from 'Y.js'
- Add .js extensions to relative imports
- Keep external packages without .js (e.g., 'tinycon/tinycon')
- Convert exports.X = Y to export {X}
- Update self-references to avoid circular dependency issues

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Convert const X = require('Y') to import X from 'Y.js'
- Convert const {A, B} = require('Y') to import {A, B} from 'Y.js'
- Add .js extensions to relative imports
- Keep external packages without .js (e.g., 'tinycon/tinycon')
- Convert exports.X = Y to export {X}
- Refactor forward references to allow function reordering

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Convert const X = require('Y') to import X from 'Y.js'
- Convert const {A, B} = require('Y') to import {A, B} from 'Y.js'
- Add .js extensions to relative imports
- Keep external packages without .js (e.g., 'tinycon/tinycon', 'underscore')
- Convert exports.X = Y to export {X}
- Convert module.exports to export default

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Convert const X = require('Y') to import X from 'Y.js'
- Add .js extensions to relative imports
- Convert exports.X = Y to export {X}
- Convert dynamic requires to dynamic imports for circular dependency handling

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Convert dynamic requires to dynamic imports for circular dependency handling
- Make timeslider.init async to support dynamic imports
- Update exports references to use module scope or window
- Add ESM export default for jquery library
- Keep CommonJS compatibility for jquery

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- pad_automatic_reconnect.ts: export const showCountDownTimerToReconnectOnModal
- pad_cookie.ts: convert to named export with const class instance
- pad_impexp.ts: export {padimpexp}
- pad_savedrevs.ts: export const saveNow, export const init
- skin_variants.ts: export multiple functions
- changesettracker.ts: export {makeChangesetTracker}
- broadcast_revisions.ts: export {loadBroadcastRevisionsJS}
- AttributeManager.ts: add .js extensions to imports, export default AttributeManager

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Convert remaining exports.baseURL references to use the baseURL const defined at module level.
This completes the conversion from CommonJS require/exports to ESM import/export syntax.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@JohnMcLear
Copy link
Copy Markdown
Member

?????

@SamTV12345
Copy link
Copy Markdown
Member Author

?????

So far that works. So we can convert to ESM and use modern test runners like vitest + have actual editor integrations. With require everything is any.

@SamTV12345 SamTV12345 closed this May 10, 2026
@SamTV12345 SamTV12345 reopened this May 16, 2026
Brings 150 commits of develop work into the backend ESM + vitest migration
branch (v2.7.3 → v3.0.0 release prep). 41 conflicts resolved, preserving
this branch's ESM structure while layering in develop's new functionality.

Conflict resolution highlights:
- CHANGELOG.md: ESM/vitest plugin-author breaking changes folded into the
  v3.0.0 entry as a new "Breaking changes for plugin authors" section.
- src/package.json: kept vitest-only test scripts, dropped mocha/mocha-froth
  devDeps, took newer @types/node and etherpad-cli-client versions.
- src/node/db/{API,AuthorManager,DB,GroupManager,Pad}.ts: ESM exports
  preserved, develop's new GDPR anonymize/search APIs, deletion-token flow,
  ueberdb2 v6, and SYSTEM_AUTHOR_ID added as ESM exports.
- src/node/handler/{APIHandler,PadMessageHandler,RestAPI,SocketIORouter}.ts:
  v1.3.1 API surface with compactPad/anonymizeAuthor, prometheus instrument
  hooks, anonymizeIp + isAcceptingConnections imports, socketioServer rename
  preserved.
- src/node/hooks/express/*: ESM imports, anonymizeIp/ensureAuthorTokenCookie/
  socialMeta wired in for v3 features.
- src/node/utils/{Settings,UpdateCheck,ImportEtherpad}.ts: createHash for
  randomVersionString determinism, axios dropped in favour of native fetch /
  undici, dynamic ueberdb2 import removed (static import works under ESM).
- src/node/server.ts: undici ProxyAgent (axios removal from develop), pkg.json
  import with `with { type: 'json' }` ESM attributes.
- src/static/js/{ace,pad,pad_editor,pad_userlist,timeslider}.ts +
  pluginfw/installer.ts: full require()→import conversion preserved,
  develop's pad_mode/showPrivacyBannerIfEnabled/pad_version_badge/
  pluginCatalogGuard/pluginEngineCheck/installerTasks imports added,
  pad_editor's focusOnLine settle-loop refactor kept.
- Backend test specs: ESM imports + .js extensions preserved, vitest harness
  in src/tests/backend/common.ts kept (with develop's diagnostic loggers
  layered in), Settings CJS-compat tests dropped (no longer applicable
  under ESM), randomVersionString + padOptions tests converted to ESM.
- Frontend specs: import unions resolved with .js extensions.
- fuzzImportTest.ts: kept deleted (removed earlier in this branch with
  mocha-froth).
- .github/workflows/backend-tests.yml: unified single `pnpm test` (vitest)
  with develop's Node diagnostic-report capture.
- pnpm-lock.yaml: taken from develop; will need `pnpm install` to reconcile
  against the merged package.json (drops mocha/mocha-froth lockfile entries).
After the develop merge, the new files from develop's side weren't
ESM-converted (this branch's mass require()→import + .js-extension pass
predated them). 271 tsc errors revealed across 87 files.

- src/node/db/DB.ts: restored closing `}` for the `if (db.metrics != null)`
  block that the merge conflict resolution dropped — was the only genuine
  merge-resolution bug.
- src/node/db/PadDeletionManager.ts: convert `exports.foo` → `export const`,
  `require('./DB')` → `import DB from './DB.js'`.
- src/node/hooks/i18n.ts: widen `locales` type to
  `{[lang]: {[key]: string}}` so renderSocialMeta's call sites typecheck.
- src/node/updater/**/*.ts, hooks/express/{openapi-admin,updateActions,
  updateStatus}.ts, prom-instruments.ts, prometheus.ts, utils/SkinColors.ts,
  utils/ensureAuthorTokenCookie.ts, static/js/pluginfw/pluginCatalogGuard.ts:
  add `.js` extensions to relative imports (static + dynamic). Fix the
  one over-broad fix: `'../../updater'` → `'../../updater/index.js'`
  (explicit dir-index import under ESM).
- tests/backend-new/**, tests/backend/specs/**, tests/frontend-new/**:
  add `.js` extensions to imports across develop's new test specs.
- tests/backend/specs/{admin,api,*}.ts: add `this: any` annotation to
  mocha-style `function () { this.timeout(N); ... }` callbacks so they
  typecheck under vitest. Runtime semantics unchanged — `this.timeout()`
  was already a no-op under the vitest harness (no mocha context shim).

`pnpm run ts-check` now passes with zero errors.
Replaces the `this: any` annotations introduced in the previous commit with
a real migration to vitest's native API. The previous fix only made tsc
green; this fix makes the test contract correct under vitest.

mocha → vitest mappings:
- `before(function () { this.timeout(N); ... })` → `before(async () => { ... })`.
  vitest.config.ts already sets `hookTimeout: 60000` and `testTimeout: 120000`,
  so the per-hook overrides were redundant. (The longer mocha-style timeout
  could be passed as the second arg to before(): `before(async () => {}, ms)`.
  None of the call sites needed it.)
- `describe('foo', function () { this.timeout(N); ... })` → `describe('foo', () => { ... })`.
  Same reason — covered by testTimeout default.
- `it(..., function () { try { require.resolve('html-to-docx'); } catch { this.skip(); } ...})`
  → hoist `const hasHtmlToDocx = canResolve(...)` to module load, then
  `describe.skipIf(!hasHtmlToDocx)(...)` or `it.skipIf(!hasHtmlToDocx)(...)`.
  Vitest evaluates skipIf at definition time, so this works for the
  require.resolve-style "skip if optional dep missing" pattern that drives
  every skip in export.ts and import.ts.
- For the one runtime-only condition (heading-block plugin registration via
  ccRegisterBlockElements, which needs common.init() to have run): keep a
  closure flag set in `before(...)` and call `ctx.skip()` inside each `it`
  that needs it. vitest exposes `skip` on the test-context parameter.
- `function ()` callbacks bulk-converted to arrow functions across the touched
  files now that no body references `this`.
- Removed `src/tests/backend/diagnostics.ts` — it was a `mocha --require` hook
  shim (mochaHooks export, this.currentTest access). Mocha was dropped from
  this branch's devDeps; nothing imports it, vitest.config doesn't load it.

`pnpm run ts-check` passes with zero errors. No `this: any` anywhere in the
test tree.
The previous merge resolution caught the obvious `require()` calls in
files with conflict markers, but several develop-side files use bare
`require()` or `exports.foo = ...` outside of conflict zones. These
compile fine under tsc (which is permissive about CJS-shape syntax in
ESM modules) but throw at runtime as soon as the module is loaded by
Node's ESM loader: `ReferenceError: require/exports is not defined in
ES module scope`.

That's what the CI surfaced — every job that boots the server or builds
the admin UI (which imports the server modules to dump the OpenAPI
spec) was failing on:
  src/node/utils/Settings.ts:1346  `require('../../package.json')`
  src/node/hooks/express/openapi.ts:874  `exports.generateDefinitionForVersion = ...`

Fixed:
- Settings.ts:1346 — replaced the inline `require(...).version` with the
  existing ESM-safe `getEpVersion()` helper (which already uses the
  module's createRequire bridge on line 884). Same value, no duplication.
- server.ts:193 — `require('./updater')` → `await import('./updater/index.js')`
  for the optional markBootHealthy() call.
- ExportHandler.ts — added a createRequire bridge and replaced the four
  inline `require()` calls (sofficeAvailable, ExportSanitizeHtml,
  html-to-docx, ExportPdfNative) with ESM imports where possible.
- ImportHandler.ts — added static ESM imports for ImportDocxNative and
  ExportSanitizeHtml; dropped the three inline `require()` calls.
- ExportPdfNative.ts, ImportDocxNative.ts — added createRequire bridges
  for the top-level CJS-only npm package requires (pdfkit, mammoth, jszip).
  These packages publish CJS entries that don't round-trip cleanly through
  ESM default-import interop under tsx; the bridge is the minimum-risk fix.
- adminsettings.ts — replaced inline `require('AuthorManager')` with a
  static `import * as authorManager`.
- pad_editbar.ts — replaced `require('./pad_mode')` with `await import(...)`
  inside the showTimeSlider click handler (which is already async-capable).
- openapi.ts:874-875 — `exports.X = X; exports.Y = Y;` → `export {X, Y};`.
- openapi-admin.ts — dropped the redundant `exports.expressPreSession =
  expressPreSession;` (the function is already `export const`) and the
  duplicate `exports.generateAdminDefinition = generateAdminDefinition;`
  (also already `export const` on the declaration line).

Verified locally:
- `pnpm run ts-check` passes.
- `admin/scripts/dump-spec.ts` — the script that booted the failing
  `dump-spec.ts failed with exit code 1` in CI — now runs to completion
  and writes a 128 KB spec.
@qodo-free-for-open-source-projects
Copy link
Copy Markdown

qodo-free-for-open-source-projects Bot commented May 16, 2026

CI Feedback 🧐

(Feedback updated until commit ad66e94)

A test triggered by this PR failed. Here is an AI-generated analysis of the failure:

Action: Playwright Firefox with plugins

Failed stage: Run the frontend tests [❌]

Failed test name: ""

Failure summary:

  • The workflow failed during the server startup step (pnpm run prod) because Etherpad could not start
    and therefore never responded on http://localhost:9001/ within the 90s readiness check (curl
    repeatedly failed, then ::error::Etherpad did not respond on :9001 within 90s).
  • Etherpad crashed due to an esbuild bundling error in static/js/pad_editor.ts: duplicate exports were
    detected:
    - static/js/pad_editor.ts:438:8 re-exports padeditor, but it was already exported at
    static/js/pad_editor.ts:300:8.
    - static/js/pad_editor.ts:438:19 re-exports focusOnLine, but it was
    already exported at static/js/pad_editor.ts:348:13.
  • As a result, the build terminated with Error: Build failed with 2 errors, and pnpm reported
    [ERR_PNPM_RECURSIVE_RUN_FIRST_FAIL] ... Exit status 1, causing the GitHub Action to exit with code
    1.
Relevant error logs:
1:  ##[group]Runner Image Provisioner
2:  Hosted Compute Agent
...

269:  │   to run scripts.                                                            │
270:  │                                                                              │
271:  ╰──────────────────────────────────────────────────────────────────────────────╯
272:  Done in 9.4s using pnpm v11.1.2
273:  ##[group]Run cp ./src/tests/settings.json settings.json
274:  �[36;1mcp ./src/tests/settings.json settings.json�[0m
275:  shell: /usr/bin/bash -e {0}
276:  env:
277:  PNPM_HOME: /home/runner/setup-pnpm/node_modules/.bin
278:  ##[endgroup]
279:  ##[group]Run set -euo pipefail
280:  �[36;1mset -euo pipefail�[0m
281:  �[36;1mpnpm run prod > /tmp/etherpad-server.log 2>&1 &�[0m
282:  �[36;1m# Generous 90s budget so a slow runner (or, in the with-plugins�[0m
283:  �[36;1m# variant, plugin boot) doesn't lose the race against the test�[0m
284:  �[36;1m# phase. Fail loudly on timeout rather than silently falling�[0m
285:  �[36;1m# through to tests against a half-started server.�[0m
286:  �[36;1m# --max-time bounds each probe so a stuck server can't make a�[0m
287:  �[36;1m# single curl call eat the whole 90s budget.�[0m
288:  �[36;1mcan_connect() { curl --max-time 3 -sSfo /dev/null http://localhost:9001/; }�[0m
289:  �[36;1mfor i in $(seq 1 90); do can_connect && break; sleep 1; done�[0m
290:  �[36;1mif ! can_connect; then�[0m
291:  �[36;1m  echo "::error::Etherpad did not respond on :9001 within 90s"�[0m
292:  �[36;1m  echo "----- server log -----"�[0m
293:  �[36;1m  tail -n 200 /tmp/etherpad-server.log || true�[0m
294:  �[36;1m  exit 1�[0m
295:  �[36;1mfi�[0m
296:  �[36;1mcd src�[0m
297:  �[36;1mpnpm exec playwright install firefox  --with-deps�[0m
298:  �[36;1mWITH_PLUGINS=1 pnpm run test-ui --project=firefox�[0m
299:  shell: /usr/bin/bash --noprofile --norc -e -o pipefail {0}
300:  env:
301:  PNPM_HOME: /home/runner/setup-pnpm/node_modules/.bin
302:  ##[endgroup]
303:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
304:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
305:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
306:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
307:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
308:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
309:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
310:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
311:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
312:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
313:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
314:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
315:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
316:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
317:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
318:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
319:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
320:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
321:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
322:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
323:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
324:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
325:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
326:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
327:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
328:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
329:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
330:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
331:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
332:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
333:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
334:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
335:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
336:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
337:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
338:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
339:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
340:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
341:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
342:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
343:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
344:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
345:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
346:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
347:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
348:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
349:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
350:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
351:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
352:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
353:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
354:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
355:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
356:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
357:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
358:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
359:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
360:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
361:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
362:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
363:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
364:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
365:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
366:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
367:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
368:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
369:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
370:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
371:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
372:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
373:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
374:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
375:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
376:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
377:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
378:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
379:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
380:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
381:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
382:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
383:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
384:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
385:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
386:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
387:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
388:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
389:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
390:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
391:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
392:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
393:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
394:  ##[error]Etherpad did not respond on :9001 within 90s
395:  ----- server log -----
396:  at resolveTsPathsSync (file:///home/runner/work/etherpad/etherpad/node_modules/.pnpm/tsx@4.22.0/node_modules/tsx/dist/register-lJYvHe5s.mjs:2:9673)
397:  at resolve2 (file:///home/runner/work/etherpad/etherpad/node_modules/.pnpm/tsx@4.22.0/node_modules/tsx/dist/register-lJYvHe5s.mjs:2:11046)
398:  at nextStep (node:internal/modules/customization_hooks:189:26)
399:  at resolveWithHooks (node:internal/modules/customization_hooks:417:10)
400:  at ModuleLoader.resolveSync (node:internal/modules/esm/loader:736:14)
401:  at #resolve (node:internal/modules/esm/loader:679:17)
402:  at ModuleLoader.getOrCreateModuleJob (node:internal/modules/esm/loader:599:35)
403:  at node:internal/modules/esm/loader:628:32
404:  �[91m[2026-05-16T21:42:29.831] [ERROR] settings - �[39mFailed to load hook function "/home/runner/work/etherpad/etherpad/src/plugin_packages/ep_readonly_guest/ep_readonly_guest:eejsBlock_permissionDenied" for plugin "ep_readonly_guest" part "ep_readonly_guest" hook set "hooks" hook "eejsBlock_permissionDenied": Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/home/runner/work/etherpad/etherpad/src/plugin_packages/ep_readonly_guest/ep_readonly_guest' imported from /home/runner/work/etherpad/etherpad/src/static/js/pluginfw/plugins.ts
405:  at finalizeResolution (node:internal/modules/esm/resolve:271:11)
406:  at moduleResolve (node:internal/modules/esm/resolve:861:10)
407:  at defaultResolve (node:internal/modules/esm/resolve:988:11)
408:  at #cachedDefaultResolve (node:internal/modules/esm/loader:697:20)
409:  at #resolveAndMaybeBlockOnLoaderThread (node:internal/modules/esm/loader:714:38)
410:  at nextStep (node:internal/modules/customization_hooks:189:26)
411:  at resolveBaseSync (file:///home/runner/work/etherpad/etherpad/node_modules/.pnpm/tsx@4.22.0/node_modules/tsx/dist/register-lJYvHe5s.mjs:2:7331)
412:  at resolveDirectorySync (file:///home/runner/work/etherpad/etherpad/node_modules/.pnpm/tsx@4.22.0/node_modules/tsx/dist/register-lJYvHe5s.mjs:2:8470)
413:  at resolveTsPathsSync (file:///home/runner/work/etherpad/etherpad/node_modules/.pnpm/tsx@4.22.0/node_modules/tsx/dist/register-lJYvHe5s.mjs:2:9673)
414:  at resolve2 (file:///home/runner/work/etherpad/etherpad/node_modules/.pnpm/tsx@4.22.0/node_modules/tsx/dist/register-lJYvHe5s.mjs:2:11046)
415:  at nextStep (node:internal/modules/customization_hooks:189:26)
416:  at resolveWithHooks (node:internal/modules/customization_hooks:417:10)
417:  at ModuleLoader.resolveSync (node:internal/modules/esm/loader:736:14)
418:  at #resolve (node:internal/modules/esm/loader:679:17)
419:  at ModuleLoader.getOrCreateModuleJob (node:internal/modules/esm/loader:599:35)
420:  at node:internal/modules/esm/loader:628:32
421:  �[91m[2026-05-16T21:42:29.837] [ERROR] settings - �[39mFailed to load hook function "/home/runner/work/etherpad/etherpad/src/plugin_packages/ep_readonly_guest/ep_readonly_guest:eejsBlock_userlist" for plugin "ep_readonly_guest" part "ep_readonly_guest" hook set "hooks" hook "eejsBlock_userlist": Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/home/runner/work/etherpad/etherpad/src/plugin_packages/ep_readonly_guest/ep_readonly_guest' imported from /home/runner/work/etherpad/etherpad/src/static/js/pluginfw/plugins.ts
422:  at finalizeResolution (node:internal/modules/esm/resolve:271:11)
423:  at moduleResolve (node:internal/modules/esm/resolve:861:10)
424:  at defaultResolve (node:internal/modules/esm/resolve:988:11)
425:  at #cachedDefaultResolve (node:internal/modules/esm/loader:697:20)
426:  at #resolveAndMaybeBlockOnLoaderThread (node:internal/modules/esm/loader:714:38)
427:  at nextStep (node:internal/modules/customization_hooks:189:26)
428:  at resolveBaseSync (file:///home/runner/work/etherpad/etherpad/node_modules/.pnpm/tsx@4.22.0/node_modules/tsx/dist/register-lJYvHe5s.mjs:2:7331)
429:  at resolveDirectorySync (file:///home/runner/work/etherpad/etherpad/node_modules/.pnpm/tsx@4.22.0/node_modules/tsx/dist/register-lJYvHe5s.mjs:2:8470)
430:  at resolveTsPathsSync (file:///home/runner/work/etherpad/etherpad/node_modules/.pnpm/tsx@4.22.0/node_modules/tsx/dist/register-lJYvHe5s.mjs:2:9673)
431:  at resolve2 (file:///home/runner/work/etherpad/etherpad/node_modules/.pnpm/tsx@4.22.0/node_modules/tsx/dist/register-lJYvHe5s.mjs:2:11046)
432:  at nextStep (node:internal/modules/customization_hooks:189:26)
433:  at resolveWithHooks (node:internal/modules/customization_hooks:417:10)
434:  at ModuleLoader.resolveSync (node:internal/modules/esm/loader:736:14)
435:  at #resolve (node:internal/modules/esm/loader:679:17)
436:  at ModuleLoader.getOrCreateModuleJob (node:internal/modules/esm/loader:599:35)
437:  at node:internal/modules/esm/loader:628:32
438:  �[91m[2026-05-16T21:42:29.843] [ERROR] settings - �[39mFailed to load hook function "/home/runner/work/etherpad/etherpad/src/plugin_packages/ep_readonly_guest/ep_readonly_guest:expressCreateServer" for plugin "ep_readonly_guest" part "ep_readonly_guest" hook set "hooks" hook "expressCreateServer": Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/home/runner/work/etherpad/etherpad/src/plugin_packages/ep_readonly_guest/ep_readonly_guest' imported from /home/runner/work/etherpad/etherpad/src/static/js/pluginfw/plugins.ts
439:  at finalizeResolution (node:internal/modules/esm/resolve:271:11)
440:  at moduleResolve (node:internal/modules/esm/resolve:861:10)
441:  at defaultResolve (node:internal/modules/esm/resolve:988:11)
442:  at #cachedDefaultResolve (node:internal/modules/esm/loader:697:20)
443:  at #resolveAndMaybeBlockOnLoaderThread (node:internal/modules/esm/loader:714:38)
444:  at nextStep (node:internal/modules/customization_hooks:189:26)
445:  at resolveBaseSync (file:///home/runner/work/etherpad/etherpad/node_modules/.pnpm/tsx@4.22.0/node_modules/tsx/dist/register-lJYvHe5s.mjs:2:7331)
446:  at resolveDirectorySync (file:///home/runner/work/etherpad/etherpad/node_modules/.pnpm/tsx@4.22.0/node_modules/tsx/dist/register-lJYvHe5s.mjs:2:8470)
447:  at resolveTsPathsSync (file:///home/runner/work/etherpad/etherpad/node_modules/.pnpm/tsx@4.22.0/node_modules/tsx/dist/register-lJYvHe5s.mjs:2:9673)
448:  at resolve2 (file:///home/runner/work/etherpad/etherpad/node_modules/.pnpm/tsx@4.22.0/node_modules/tsx/dist/register-lJYvHe5s.mjs:2:11046)
449:  at nextStep (node:internal/modules/customization_hooks:189:26)
450:  at resolveWithHooks (node:internal/modules/customization_hooks:417:10)
451:  at ModuleLoader.resolveSync (node:internal/modules/esm/loader:736:14)
452:  at #resolve (node:internal/modules/esm/loader:679:17)
453:  at ModuleLoader.getOrCreateModuleJob (node:internal/modules/esm/loader:599:35)
454:  at node:internal/modules/esm/loader:628:32
455:  �[91m[2026-05-16T21:42:29.850] [ERROR] settings - �[39mFailed to load hook function "/home/runner/work/etherpad/etherpad/src/plugin_packages/ep_readonly_guest/ep_readonly_guest:handleMessage" for plugin "ep_readonly_guest" part "ep_readonly_guest" hook set "hooks" hook "handleMessage": Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/home/runner/work/etherpad/etherpad/src/plugin_packages/ep_readonly_guest/ep_readonly_guest' imported from /home/runner/work/etherpad/etherpad/src/static/js/pluginfw/plugins.ts
456:  at finalizeResolution (node:internal/modules/esm/resolve:271:11)
457:  at moduleResolve (node:internal/modules/esm/resolve:861:10)
458:  at defaultResolve (node:internal/modules/esm/resolve:988:11)
459:  at #cachedDefaultResolve (node:internal/modules/esm/loader:697:20)
460:  at #resolveAndMaybeBlockOnLoaderThread (node:internal/modules/esm/loader:714:38)
461:  at nextStep (node:internal/modules/customization_hooks:189:26)
462:  at resolveBaseSync (file:///home/runner/work/etherpad/etherpad/node_modules/.pnpm/tsx@4.22.0/node_modules/tsx/dist/register-lJYvHe5s.mjs:2:7331)
463:  at resolveDirectorySync (file:///home/runner/work/etherpad/etherpad/node_modules/.pnpm/tsx@4.22.0/node_modules/tsx/dist/register-lJYvHe5s.mjs:2:8470)
464:  at resolveTsPathsSync (file:///home/runner/work/etherpad/etherpad/node_modules/.pnpm/tsx@4.22.0/node_modules/tsx/dist/register-lJYvHe5s.mjs:2:9673)
465:  at resolve2 (file:///home/runner/work/etherpad/etherpad/node_modules/.pnpm/tsx@4.22.0/node_modules/tsx/dist/register-lJYvHe5s.mjs:2:11046)
466:  at nextStep (node:internal/modules/customization_hooks:189:26)
467:  at resolveWithHooks (node:internal/modules/customization_hooks:417:10)
468:  at ModuleLoader.resolveSync (node:internal/modules/esm/loader:736:14)
469:  at #resolve (node:internal/modules/esm/loader:679:17)
470:  at ModuleLoader.getOrCreateModuleJob (node:internal/modules/esm/loader:599:35)
471:  at node:internal/modules/esm/loader:628:32
472:  �[91m[2026-05-16T21:42:29.856] [ERROR] settings - �[39mFailed to load hook function "/home/runner/work/etherpad/etherpad/src/plugin_packages/ep_readonly_guest/ep_readonly_guest:loadSettings" for plugin "ep_readonly_guest" part "ep_readonly_guest" hook set "hooks" hook "loadSettings": Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/home/runner/work/etherpad/etherpad/src/plugin_packages/ep_readonly_guest/ep_readonly_guest' imported from /home/runner/work/etherpad/etherpad/src/static/js/pluginfw/plugins.ts
473:  at finalizeResolution (node:internal/modules/esm/resolve:271:11)
474:  at moduleResolve (node:internal/modules/esm/resolve:861:10)
475:  at defaultResolve (node:internal/modules/esm/resolve:988:11)
476:  at #cachedDefaultResolve (node:internal/modules/esm/loader:697:20)
477:  at #resolveAndMaybeBlockOnLoaderThread (node:internal/modules/esm/loader:714:38)
478:  at nextStep (node:internal/modules/customization_hooks:189:26)
479:  at resolveBaseSync (file:///home/runner/work/etherpad/etherpad/node_modules/.pnpm/tsx@4.22.0/node_modules/tsx/dist/register-lJYvHe5s.mjs:2:7331)
480:  at resolveDirectorySync (file:///home/runner/work/etherpad/etherpad/node_modules/.pnpm/tsx@4.22.0/node_modules/tsx/dist/register-lJYvHe5s.mjs:2:8470)
481:  at resolveTsPathsSync (file:///home/runner/work/etherpad/etherpad/node_modules/.pnpm/tsx@4.22.0/node_modules/tsx/dist/register-lJYvHe5s.mjs:2:9673)
482:  at resolve2 (file:///home/runner/work/etherpad/etherpad/node_modules/.pnpm/tsx@4.22.0/node_modules/tsx/dist/register-lJYvHe5s.mjs:2:11046)
483:  at nextStep (node:internal/modules/customization_hooks:189:26)
484:  at resolveWithHooks (node:internal/modules/customization_hooks:417:10)
485:  at ModuleLoader.resolveSync (node:internal/modules/esm/loader:736:14)
486:  at #resolve (node:internal/modules/esm/loader:679:17)
487:  at ModuleLoader.getOrCreateModuleJob (node:internal/modules/esm/loader:599:35)
488:  at node:internal/modules/esm/loader:628:32
489:  �[91m[2026-05-16T21:42:29.862] [ERROR] settings - �[39mFailed to load hook function "/home/runner/work/etherpad/etherpad/src/plugin_packages/ep_readonly_guest/ep_readonly_guest:preAuthorize" for plugin "ep_readonly_guest" part "ep_readonly_guest" hook set "hooks" hook "preAuthorize": Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/home/runner/work/etherpad/etherpad/src/plugin_packages/ep_readonly_guest/ep_readonly_guest' imported from /home/runner/work/etherpad/etherpad/src/static/js/pluginfw/plugins.ts
490:  at finalizeResolution (node:internal/modules/esm/resolve:271:11)
...

494:  at #resolveAndMaybeBlockOnLoaderThread (node:internal/modules/esm/loader:714:38)
495:  at nextStep (node:internal/modules/customization_hooks:189:26)
496:  at resolveBaseSync (file:///home/runner/work/etherpad/etherpad/node_modules/.pnpm/tsx@4.22.0/node_modules/tsx/dist/register-lJYvHe5s.mjs:2:7331)
497:  at resolveDirectorySync (file:///home/runner/work/etherpad/etherpad/node_modules/.pnpm/tsx@4.22.0/node_modules/tsx/dist/register-lJYvHe5s.mjs:2:8470)
498:  at resolveTsPathsSync (file:///home/runner/work/etherpad/etherpad/node_modules/.pnpm/tsx@4.22.0/node_modules/tsx/dist/register-lJYvHe5s.mjs:2:9673)
499:  at resolve2 (file:///home/runner/work/etherpad/etherpad/node_modules/.pnpm/tsx@4.22.0/node_modules/tsx/dist/register-lJYvHe5s.mjs:2:11046)
500:  at nextStep (node:internal/modules/customization_hooks:189:26)
501:  at resolveWithHooks (node:internal/modules/customization_hooks:417:10)
502:  at ModuleLoader.resolveSync (node:internal/modules/esm/loader:736:14)
503:  at #resolve (node:internal/modules/esm/loader:679:17)
504:  at ModuleLoader.getOrCreateModuleJob (node:internal/modules/esm/loader:599:35)
505:  at node:internal/modules/esm/loader:628:32
506:  �[32m[2026-05-16T21:42:29.922] [INFO] server - �[39mInstalled plugins: ep_align@11.0.29, ep_font_color@0.0.137, ep_author_hover@11.0.28, ep_readonly_guest@1.0.53, ep_hash_auth@11.0.24, ep_spellcheck@0.0.101, ep_markdown@12.0.9, ep_set_title_on_pad@0.7.6, ep_subscript_and_superscript@0.3.67, ep_table_of_contents@0.4.7, ep_font_size@0.4.109, ep_plugin_helpers@0.5.3, ep_headings2@0.2.119
507:  �[32m[2026-05-16T21:42:30.043] [INFO] settings - �[39mReport bugs at https://github.com/ether/etherpad/issues
508:  �[32m[2026-05-16T21:42:30.043] [INFO] settings - �[39mYour Etherpad version is 3.0.0 (ad66e94)
509:  ✘ [ERROR] Multiple exports with the same name "padeditor"
510:  static/js/pad_editor.ts:438:8:
511:  438 │ export {padeditor, focusOnLine};
512:  ╵         ~~~~~~~~~
513:  The name "padeditor" was originally exported here:
514:  static/js/pad_editor.ts:300:8:
515:  300 │ export {padeditor};
516:  ╵         ~~~~~~~~~
517:  ✘ [ERROR] Multiple exports with the same name "focusOnLine"
518:  static/js/pad_editor.ts:438:19:
519:  438 │ export {padeditor, focusOnLine};
520:  ╵                    ~~~~~~~~~~~
521:  The name "focusOnLine" was originally exported here:
522:  static/js/pad_editor.ts:348:13:
523:  348 │ export const focusOnLine = (ace) => {
524:  ╵              ~~~~~~~~~~~
525:  ▲ [WARNING] The CommonJS "module" variable is treated as a global variable in an ECMAScript module and may not work as expected [commonjs-variable-in-esm]
526:  static/js/vendors/jquery.ts:25:4:
527:  25 │     module.exports = global.document ?
528:  ╵     ~~~~~~
529:  This file is considered to be an ECMAScript module because of the "export" keyword here:
530:  static/js/vendors/jquery.ts:10715:0:
531:  10715 │ export default (typeof window !== "undefined" && typeof window....
532:  ╵ ~~~~~~
533:  �[91m[2026-05-16T21:42:30.724] [ERROR] server - �[39mError occurred while starting Etherpad
534:  �[91m[2026-05-16T21:42:30.725] [ERROR] server - �[39mMetrics at time of fatal error:
535:  {
536:  "httpStartTime": 0,
537:  "memoryUsage": 400764928,
538:  "memoryUsageHeap": 187272080,
539:  "ueberdb_lockAwaits": 0,
540:  "ueberdb_lockAcquires": 1,
541:  "ueberdb_lockReleases": 1,
542:  "ueberdb_reads": 0,
543:  "ueberdb_readsFailed": 0,
544:  "ueberdb_readsFinished": 0,
545:  "ueberdb_readsFromCache": 0,
546:  "ueberdb_readsFromDb": 0,
547:  "ueberdb_readsFromDbFailed": 0,
548:  "ueberdb_readsFromDbFinished": 0,
549:  "ueberdb_writes": 1,
550:  "ueberdb_writesFailed": 0,
551:  "ueberdb_writesFinished": 1,
552:  "ueberdb_writesObsoleted": 0,
553:  "ueberdb_writesToDb": 1,
554:  "ueberdb_writesToDbFailed": 0,
555:  "ueberdb_writesToDbFinished": 1,
556:  "ueberdb_writesToDbRetried": 0,
557:  "totalUsers": 0,
558:  "activePads": 0
559:  }
560:  �[91m[2026-05-16T21:42:30.725] [ERROR] server - �[39mError: Build failed with 2 errors:
561:  static/js/pad_editor.ts:438:8: ERROR: Multiple exports with the same name "padeditor"
562:  static/js/pad_editor.ts:438:19: ERROR: Multiple exports with the same name "focusOnLine"
563:  at failureErrorWithLog (/home/runner/work/etherpad/etherpad/node_modules/.pnpm/esbuild@0.28.0/node_modules/esbuild/lib/main.js:1748:15)
564:  at /home/runner/work/etherpad/etherpad/node_modules/.pnpm/esbuild@0.28.0/node_modules/esbuild/lib/main.js:1207:25
565:  at /home/runner/work/etherpad/etherpad/node_modules/.pnpm/esbuild@0.28.0/node_modules/esbuild/lib/main.js:1159:52
566:  at buildResponseToResult (/home/runner/work/etherpad/etherpad/node_modules/.pnpm/esbuild@0.28.0/node_modules/esbuild/lib/main.js:1205:7)
567:  at /home/runner/work/etherpad/etherpad/node_modules/.pnpm/esbuild@0.28.0/node_modules/esbuild/lib/main.js:1232:16
568:  at responseCallbacks.<computed> (/home/runner/work/etherpad/etherpad/node_modules/.pnpm/esbuild@0.28.0/node_modules/esbuild/lib/main.js:884:9)
569:  at handleIncomingPacket (/home/runner/work/etherpad/etherpad/node_modules/.pnpm/esbuild@0.28.0/node_modules/esbuild/lib/main.js:939:12)
570:  at Socket.readFromStdout (/home/runner/work/etherpad/etherpad/node_modules/.pnpm/esbuild@0.28.0/node_modules/esbuild/lib/main.js:862:7)
571:  at Socket.emit (node:events:509:28)
572:  at addChunk (node:internal/streams/readable:563:12)
573:  �[32m[2026-05-16T21:42:30.725] [INFO] server - �[39mExiting...
574:  �[32m[2026-05-16T21:42:30.725] [INFO] server - �[39mWaiting for Node.js to exit...
575:  �[32m[2026-05-16T21:42:30.735] [INFO] plugins - �[39mpnpm --version: 11.1.2
576:  �[32m[2026-05-16T21:42:30.736] [INFO] updater - �[39mupdater: install method = git, tier = notify
577:  �[91m[2026-05-16T21:42:35.725] [ERROR] server - �[39mSomething that should have been cleaned up during the shutdown hook (such as a timer, worker thread, or open connection) is preventing Node.js from exiting
578:  �[91m[2026-05-16T21:42:35.725] [ERROR] server - �[39mEnable `dumpOnUncleanExit` setting to get a dump of objects preventing a clean exit
579:  �[91m[2026-05-16T21:42:35.725] [ERROR] server - �[39mForcing an unclean exit...
580:  /home/runner/work/etherpad/etherpad/src:
581:  [ERR_PNPM_RECURSIVE_RUN_FIRST_FAIL] ep_etherpad-lite@3.0.0 prod: `cross-env NODE_ENV=production node --import tsx node/server.ts`
582:  Exit status 1
583:  [ELIFECYCLE] Command failed with exit code 1.
584:  ##[error]Process completed with exit code 1.
585:  ##[group]Run actions/upload-artifact@v7

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants