agalwood/Motrix · error · PluginCodedError
plugin.capability.unavailable
plugin.capability.unavailable
Error message
unknown log method: ${msg.method} What it means
Thrown by dispatchLog when the args parsed successfully but msg.method does not name a function on the host logger instance (looked up dynamically at capability-bridge.ts:604-606). Only log levels actually present on the logger are callable; any other method name is rejected as plugin.capability.unavailable.
Source
Thrown at src/core/plugin/host/capability-bridge.ts:608
// -------------------------------------------------------------------------
// log
// -------------------------------------------------------------------------
private dispatchLog(msg: BridgeCallMessage): void {
const parsed = logArgsSchema.safeParse(msg.args)
if (!parsed.success) {
throw new PluginCodedError(
'plugin.capability.bad_args',
`log.${msg.method}: invalid args`
)
}
const [text, ...rest] = parsed.data
const fields = rest[0] as Record<string, unknown> | undefined
const fn = (
this.log as unknown as Record<string, (m: string, f?: object) => void>
)[msg.method]
if (typeof fn !== 'function') {
throw new PluginCodedError(
'plugin.capability.unavailable',
`unknown log method: ${msg.method}`
)
}
fn.call(this.log, String(text), fields)
}
// -------------------------------------------------------------------------
// app — snapshot only; worker reads app.* from the init message.
// Provide it here for completeness in case worker calls it post-init.
// -------------------------------------------------------------------------
private dispatchApp(_msg: BridgeCallMessage): unknown {
return this.opts.capabilityHost.appSnapshot()
}
// -------------------------------------------------------------------------
// i18nView on GitHub (pinned to 1a708ee577)
Solutions
- Use only the standard levels the host logger exposes (typically info, warn, error, debug, trace).
- Map fatal -> error and verbose/silly -> debug in the worker-side log proxy.
- Inspect the host logger object to confirm which level methods exist before wiring the plugin.
Example fix
// before
log.fatal('disk full')
// after
log.error('disk full') Defensive patterns
Strategy: type-guard
Validate before calling
const KNOWN_LOG_METHODS = ['info','warn','error','debug','trace'] as const
function isKnownLogMethod(m: string): boolean {
return (KNOWN_LOG_METHODS as readonly string[]).includes(m)
} Type guard
function isLogLevel(m: string): m is 'info'|'warn'|'error'|'debug'|'trace' {
return ['info','warn','error','debug','trace'].includes(m)
} Try / catch
try { (log as any)[method](msg, fields) }
catch (e) {
if (e instanceof Error && e.code === 'plugin.capability.unavailable') {
log.error(msg, fields) // downgrade to a known level
return
}
throw e
} Prevention
- Expose the host logger's level list in the plugin typings so authors know what is callable.
- Map fatal->error in the worker proxy if migrating from a logger with extra levels.
- Avoid dynamic method names from untrusted input.
When it happens
Trigger: Plugin calls log.fatal() when the host logger has no fatal method, or any typo / unsupported level such as log.silly(), log.verbose(), log.log().
Common situations: Plugin ported from a logger with extra levels (fatal, silly, verbose); version skew where the host logger was trimmed; typo in the method name; plugin assumes console-style log.log().
Related errors
- plugin.capability.bad_args
- plugin.fs.task.not_available_outside_hook
- plugin.metadata.not_available_outside_hook
- plugin.commands.id_out_of_namespace
- plugin.command.not_declared_in_manifest
AI-assisted analysis of agalwood/Motrix@1a708ee577 (2026-08-12).
Data as JSON: /api/errors/0045d1e910315273.
Report an issue: GitHub.