fix(matrix): resolve crypto bootstrap failure and multi-extension idHint warning#53298
Conversation
Greptile SummaryThis PR fixes two plugin-load failures on source-checkout startup: a
Confidence Score: 4/5
Prompt To Fix All With AIThis is a comment left during a code review.
Path: src/plugins/bundled-plugin-metadata.generated.ts
Line: 1549
Comment:
**`idHint` format not recognised by `isCompatiblePluginIdHint`**
Because `extensions/matrix/package.json` now has two entries in `extensions`, `scripts/generate-bundled-plugin-metadata.mjs`'s `deriveIdHint` sets `hasMultipleExtensions: true` and returns `"${normalizedPackageId}/${base}"` → `"matrix/index"`.
`isCompatiblePluginIdHint` in `src/plugins/manifest-registry.ts` only recognises the exact manifest ID or the four well-known suffixes (`-provider`, `-plugin`, `-sandbox`, `-media-understanding`); `"matrix/index"` matches none of those for the manifest ID `"matrix"`. That means every time the bundled plugin metadata is used (i.e. every `openclaw` invocation), a `warn`-level diagnostic is emitted:
> `plugin id mismatch (manifest uses "matrix", entry hints "matrix/index")`
The diagnostic doesn't stop the plugin from loading, but it does pollute the registry's diagnostic array and may surface in CLI output or `diagnostics` commands.
The cleanest fix is to extend `isCompatiblePluginIdHint` to also accept the `{id}/{anything}` form that the generator now produces:
```ts
// manifest-registry.ts
function isCompatiblePluginIdHint(idHint: string | undefined, manifestId: string): boolean {
const normalizedHint = idHint?.trim();
if (!normalizedHint) return true;
if (normalizedHint === manifestId) return true;
// Generated idHint for multi-extension plugins takes the form "id/entryBase"
if (normalizedHint.startsWith(`${manifestId}/`)) return true;
return (
normalizedHint === `${manifestId}-provider` ||
normalizedHint === `${manifestId}-plugin` ||
normalizedHint === `${manifestId}-sandbox` ||
normalizedHint === `${manifestId}-media-understanding`
);
}
```
Alternatively, the generator's `deriveIdHint` could keep returning just `normalizedPackageId` regardless of `hasMultipleExtensions`, since the disambiguation is not actually needed by any consumer.
How can I resolve this? If you propose a fix, please make it concise.Reviews (1): Last reviewed commit: "fix(line,matrix): resolve plugin load fa..." | Re-trigger Greptile |
| { | ||
| dirName: "matrix", | ||
| idHint: "matrix", | ||
| idHint: "matrix/index", |
There was a problem hiding this comment.
idHint format not recognised by isCompatiblePluginIdHint
Because extensions/matrix/package.json now has two entries in extensions, scripts/generate-bundled-plugin-metadata.mjs's deriveIdHint sets hasMultipleExtensions: true and returns "${normalizedPackageId}/${base}" → "matrix/index".
isCompatiblePluginIdHint in src/plugins/manifest-registry.ts only recognises the exact manifest ID or the four well-known suffixes (-provider, -plugin, -sandbox, -media-understanding); "matrix/index" matches none of those for the manifest ID "matrix". That means every time the bundled plugin metadata is used (i.e. every openclaw invocation), a warn-level diagnostic is emitted:
plugin id mismatch (manifest uses "matrix", entry hints "matrix/index")
The diagnostic doesn't stop the plugin from loading, but it does pollute the registry's diagnostic array and may surface in CLI output or diagnostics commands.
The cleanest fix is to extend isCompatiblePluginIdHint to also accept the {id}/{anything} form that the generator now produces:
// manifest-registry.ts
function isCompatiblePluginIdHint(idHint: string | undefined, manifestId: string): boolean {
const normalizedHint = idHint?.trim();
if (!normalizedHint) return true;
if (normalizedHint === manifestId) return true;
// Generated idHint for multi-extension plugins takes the form "id/entryBase"
if (normalizedHint.startsWith(`${manifestId}/`)) return true;
return (
normalizedHint === `${manifestId}-provider` ||
normalizedHint === `${manifestId}-plugin` ||
normalizedHint === `${manifestId}-sandbox` ||
normalizedHint === `${manifestId}-media-understanding`
);
}Alternatively, the generator's deriveIdHint could keep returning just normalizedPackageId regardless of hasMultipleExtensions, since the disambiguation is not actually needed by any consumer.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/plugins/bundled-plugin-metadata.generated.ts
Line: 1549
Comment:
**`idHint` format not recognised by `isCompatiblePluginIdHint`**
Because `extensions/matrix/package.json` now has two entries in `extensions`, `scripts/generate-bundled-plugin-metadata.mjs`'s `deriveIdHint` sets `hasMultipleExtensions: true` and returns `"${normalizedPackageId}/${base}"` → `"matrix/index"`.
`isCompatiblePluginIdHint` in `src/plugins/manifest-registry.ts` only recognises the exact manifest ID or the four well-known suffixes (`-provider`, `-plugin`, `-sandbox`, `-media-understanding`); `"matrix/index"` matches none of those for the manifest ID `"matrix"`. That means every time the bundled plugin metadata is used (i.e. every `openclaw` invocation), a `warn`-level diagnostic is emitted:
> `plugin id mismatch (manifest uses "matrix", entry hints "matrix/index")`
The diagnostic doesn't stop the plugin from loading, but it does pollute the registry's diagnostic array and may surface in CLI output or `diagnostics` commands.
The cleanest fix is to extend `isCompatiblePluginIdHint` to also accept the `{id}/{anything}` form that the generator now produces:
```ts
// manifest-registry.ts
function isCompatiblePluginIdHint(idHint: string | undefined, manifestId: string): boolean {
const normalizedHint = idHint?.trim();
if (!normalizedHint) return true;
if (normalizedHint === manifestId) return true;
// Generated idHint for multi-extension plugins takes the form "id/entryBase"
if (normalizedHint.startsWith(`${manifestId}/`)) return true;
return (
normalizedHint === `${manifestId}-provider` ||
normalizedHint === `${manifestId}-plugin` ||
normalizedHint === `${manifestId}-sandbox` ||
normalizedHint === `${manifestId}-media-understanding`
);
}
```
Alternatively, the generator's `deriveIdHint` could keep returning just `normalizedPackageId` regardless of `hasMultipleExtensions`, since the disambiguation is not actually needed by any consumer.
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
Pull request overview
Fixes recurring plugin load failures in source-checkout mode by removing a problematic LINE runtime self-import that caused duplicate star-export collisions, and by making Matrix’s crypto bootstrap runtime loadable via dynamic import during source-checkout startup.
Changes:
- LINE: remove
openclaw/plugin-sdk/line-runtimeself-import fromextensions/line/runtime-api.tsand export needed modules directly to avoidCannot redefine propertyerrors under jiti. - Matrix: ensure
src/plugin-entry.runtime.tsis built (added toopenclaw.extensions) and add an ESM.jswrapper to allow nativeimport()to work in source checkouts. - Regenerate bundled plugin metadata to reflect Matrix’s additional extension entry.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
extensions/line/runtime-api.ts |
Removes the self-import path that caused duplicate export collisions; adds direct exports for modules previously reachable via the SDK barrel. |
extensions/matrix/package.json |
Adds ./src/plugin-entry.runtime.ts to openclaw.extensions so it’s compiled to dist for production. |
extensions/matrix/src/plugin-entry.runtime.js |
Adds an ESM wrapper that uses jiti to load the TS runtime in source-checkout mode. |
src/plugins/bundled-plugin-metadata.generated.ts |
Updates generated bundled metadata for Matrix (additional extension entry; idHint change). |
| { | ||
| dirName: "matrix", | ||
| idHint: "matrix", | ||
| idHint: "matrix/index", |
There was a problem hiding this comment.
idHint is now "matrix/index", but the bundled Matrix manifest id is "matrix". manifest-registry.ts treats this as an incompatible hint and will emit a startup warning (plugin id mismatch ... entry hints "matrix/index"). Consider keeping idHint compatible with the manifest id for the primary bundled entry (e.g., adjust the bundled metadata generator so multi-extension packages don't append "/index" to the first entry), to avoid introducing a new always-on warning during plugin discovery.
| idHint: "matrix/index", | |
| idHint: "matrix", |
| export const ensureMatrixCryptoRuntime = mod.ensureMatrixCryptoRuntime; | ||
| export const handleVerifyRecoveryKey = mod.handleVerifyRecoveryKey; | ||
| export const handleVerificationBootstrap = mod.handleVerificationBootstrap; | ||
| export const handleVerificationStatus = mod.handleVerificationStatus; |
There was a problem hiding this comment.
This wrapper is critical to source-checkout startup, but there’s no regression test covering that import("./src/plugin-entry.runtime.js") succeeds and provides the expected named exports. Adding a small Matrix extension test that imports this wrapper (via the same Jiti path the plugin loader uses) and asserts the exported functions exist would help prevent future startup regressions.
| export const ensureMatrixCryptoRuntime = mod.ensureMatrixCryptoRuntime; | |
| export const handleVerifyRecoveryKey = mod.handleVerifyRecoveryKey; | |
| export const handleVerificationBootstrap = mod.handleVerificationBootstrap; | |
| export const handleVerificationStatus = mod.handleVerificationStatus; | |
| const { | |
| ensureMatrixCryptoRuntime, | |
| handleVerifyRecoveryKey, | |
| handleVerificationBootstrap, | |
| handleVerificationStatus, | |
| } = mod; | |
| for (const [name, fn] of Object.entries({ | |
| ensureMatrixCryptoRuntime, | |
| handleVerifyRecoveryKey, | |
| handleVerificationBootstrap, | |
| handleVerificationStatus, | |
| })) { | |
| if (typeof fn !== "function") { | |
| throw new Error( | |
| `Expected '${name}' to be a function exported from ./plugin-entry.runtime.ts` | |
| ); | |
| } | |
| } | |
| export { | |
| ensureMatrixCryptoRuntime, | |
| handleVerifyRecoveryKey, | |
| handleVerificationBootstrap, | |
| handleVerificationStatus, | |
| }; |
e05d3cc to
2880add
Compare
016914e to
2b050e2
Compare
2b050e2 to
85e29ad
Compare
…int warning Add ./src/plugin-entry.runtime.ts to the matrix openclaw.extensions build entry list so tsdown compiles it to dist, and add a thin ESM .js wrapper in the source tree so that native dynamic import() resolves correctly in source-checkout mode (jiti only intercepts require, not import). Extend isCompatiblePluginIdHint to accept the id/entryBase format that deriveIdHint produces for multi-extension plugins, preventing a spurious warn diagnostic on every CLI invocation. Co-Authored-By: Claude Opus 4.6 <[email protected]>
85e29ad to
6f5813f
Compare
|
Merged via squash.
Thanks @keithce! |
…int warning (openclaw#53298) Merged via squash. Prepared head SHA: 6f5813f Co-authored-by: keithce <[email protected]> Co-authored-by: gumadeiras <[email protected]> Reviewed-by: @gumadeiras
…int warning (openclaw#53298) Merged via squash. Prepared head SHA: 6f5813f Co-authored-by: keithce <[email protected]> Co-authored-by: gumadeiras <[email protected]> Reviewed-by: @gumadeiras
…int warning (openclaw#53298) Merged via squash. Prepared head SHA: 6f5813f Co-authored-by: keithce <[email protected]> Co-authored-by: gumadeiras <[email protected]> Reviewed-by: @gumadeiras
Summary
Fixes two issues with the Matrix plugin on current
main:Cannot read properties of undefined (reading 'ensureMatrixCryptoRuntime')— reported on every CLI invocationplugin id mismatch (manifest uses "matrix", entry hints "matrix/index")— emitted after the build entry fix introduces a second extension entryReproduction
After the matrix
package.jsonfix alone, a new warning appears on every invocation:Root Cause & Fix
Matrix:
plugin-entry.runtime.tsnot loadable in source-checkout modeextensions/matrix/index.tsdynamically imports./src/plugin-entry.runtime.jsat registration time for crypto bootstrap. Two issues:src/plugin-entry.runtime.tswas not listed inopenclaw.extensionsinpackage.json, so tsdown never compiled it todist/extensions/matrix/src/plugin-entry.runtime.js.extensions/tree (viaisSourceCheckoutRootinsrc/plugins/bundled-dir.ts). Nativeimport()inside a jiti-loaded module uses Node's ESM loader, which cannot resolve.js→.ts. The.jsfile doesn't exist in the source tree — only.tsdoes.Fix:
./src/plugin-entry.runtime.tsto theopenclaw.extensionsarray inextensions/matrix/package.jsonso it's compiled to dist for production builds.jswrapper atextensions/matrix/src/plugin-entry.runtime.jsthat uses jiti to load the.tssource, bridging the gap for source-checkout modeMulti-extension idHint format not recognised
Adding a second entry to
openclaw.extensionscausesderiveIdHintin the metadata generator to return"matrix/index"instead of"matrix".isCompatiblePluginIdHintinsrc/plugins/manifest-registry.tsonly accepts exact matches and four well-known suffixes — not the{id}/{entryBase}form.Fix: Add a
startsWith(\${manifestId}/`)check toisCompatiblePluginIdHint` so multi-extension idHints are accepted.Files changed
extensions/matrix/package.json— add build entryextensions/matrix/src/plugin-entry.runtime.js— new ESM wrapper for source-checkout modesrc/plugins/manifest-registry.ts— accept multi-extension idHint formatsrc/plugins/bundled-plugin-metadata.generated.ts— regeneratedTest plan
pnpm buildsucceedsopenclaw models listshows nomatrix: failed loading crypto bootstrap runtimeerrorsopenclaw models listshows noplugin id mismatchwarningspnpm checkpasses (pre-existing msteams/ui tsgo errors excluded)pnpm test -- src/plugins/manifest-registry.test.ts --runpasses (26/26)pnpm test -- extensions/matrix/src/matrix/client/file-sync-store.test.ts --runpasses (7/7)🤖 Generated with Claude Code