agalwood/Motrix · error · AppError
PluginManifestInvalid
PluginManifestInvalid
Error message
plugin.command.schema_compile_failed: ${cmd.id} What it means
Thrown at plugin install time by SchemaCache.installCommandSchemas when Ajv.compile throws on a command's argsSchema or resultSchema. The host compiles both schemas for every public command before the plugin is usable, so a malformed JSON Schema aborts installation with ErrorCode.PluginManifestInvalid. The original Ajv message is attached as the third AppError argument for diagnosis.
Source
Thrown at src/core/plugin/commands/schema-cache.ts:62
const compiled = new Map<string, CompiledPair>()
for (const cmd of cmds) {
if (
cmd.public !== true ||
cmd.argsSchema === undefined ||
cmd.resultSchema === undefined
) {
continue
}
let args: ValidateFunction
let result: ValidateFunction
try {
// Ajv typings demand AnySchema; the manifest layer passes us raw
// JSON which we have not yet validated, so we widen here and rely
// on Ajv to throw on malformed input (caught below).
args = this.ajv.compile(cmd.argsSchema as AnySchema)
result = this.ajv.compile(cmd.resultSchema as AnySchema)
} catch (cause) {
throw new AppError(
ErrorCode.PluginManifestInvalid,
`plugin.command.schema_compile_failed: ${cmd.id}`,
cause instanceof Error ? cause.message : String(cause)
)
}
compiled.set(cmd.id, { args, result })
}
this.byPlugin.set(pluginId, compiled)
}
validateArgs(pluginId: string, commandId: string, args: unknown): void {
const pair = this.byPlugin.get(pluginId)?.get(commandId)
if (!pair) {
throw new AppError(
ErrorCode.PluginRuntimeFault,
'plugin.command.not_public'
)
}View on GitHub (pinned to 1a708ee577)
Solutions
- Read the attached cause message (third AppError arg) — Ajv names the offending keyword and path.
- Validate the schema against a JSON-Schema meta-schema or ajv.compile it in isolation during development to catch the error before install.
- Align the schema with JSON-Schema draft-07 (the Ajv default) and avoid keywords Ajv strict mode flags.
- If the command should not be host-validated, set public:false (or omit it) so it is skipped — but then it cannot be invoked cross-plugin.
Example fix
// before
{ id: "acme.f.run", public: true,
argsSchema: { typee: "object" },
resultSchema: { type: "object" } }
// after
{ id: "acme.f.run", public: true,
argsSchema: { type: "object", properties: {} },
resultSchema: { type: "object", properties: {} } } Defensive patterns
Strategy: validation
Validate before calling
import Ajv from 'ajv'
const ajv = new Ajv({ strict: true, useDefaults: false })
function schemaCompiles(s: unknown): boolean { try { ajv.compile(s as any); return true } catch { return false } } Try / catch
try { schemaCache.installCommandSchemas(pluginId, cmds) }
catch (e) { if (e.message.startsWith('plugin.command.schema_compile_failed')) { /* fix schema from e cause text */ } else throw e } Prevention
- Validate every manifest schema with ajv.compile in CI before publish.
- Use JSON-Schema draft-07 compatible keywords only.
- Read the attached cause message to find the offending keyword/path.
When it happens
Trigger: A public command (public:true) whose argsSchema or resultSchema is not a valid JSON Schema digestible by Ajv in strict mode — e.g. a $ref that resolves nowhere, an unknown keyword under strict:true, a schema that is not an object (bare string used incorrectly), or a draft-incompatible construct.
Common situations: Hand-written manifests with typos in keywords ("typee":"string"), schemas copy-pasted from a different JSON-Schema draft, use of ajv-keywords/formats without registering them, or $ref targets that were renamed. Ajv strict mode (set on the cache at schema-cache.ts:33-37) also rejects many schemas that other validators accept.
Related errors
- plugin.command.not_declared_in_manifest
- PluginRuntimeFault
- plugin.manifest.role.requires_builtin
- transient-failure
- Invalid Task Inspector Activity snapshot
AI-assisted analysis of agalwood/Motrix@1a708ee577 (2026-08-12).
Data as JSON: /api/errors/424d2b1befb75ca1.
Report an issue: GitHub.