{"record":{"id":"0045d1e910315273","repo":"agalwood/Motrix","slug":"plugin-capability-unavailable-0045d1","errorCode":"plugin.capability.unavailable","errorMessage":"unknown log method: ${msg.method}","messagePattern":"unknown log method: (.+?)","errorType":"exception","errorClass":"PluginCodedError","httpStatus":null,"severity":"error","filePath":"src/core/plugin/host/capability-bridge.ts","lineNumber":608,"sourceCode":"  // -------------------------------------------------------------------------\n  // log\n  // -------------------------------------------------------------------------\n\n  private dispatchLog(msg: BridgeCallMessage): void {\n    const parsed = logArgsSchema.safeParse(msg.args)\n    if (!parsed.success) {\n      throw new PluginCodedError(\n        'plugin.capability.bad_args',\n        `log.${msg.method}: invalid args`\n      )\n    }\n    const [text, ...rest] = parsed.data\n    const fields = rest[0] as Record<string, unknown> | undefined\n    const fn = (\n      this.log as unknown as Record<string, (m: string, f?: object) => void>\n    )[msg.method]\n    if (typeof fn !== 'function') {\n      throw new PluginCodedError(\n        'plugin.capability.unavailable',\n        `unknown log method: ${msg.method}`\n      )\n    }\n    fn.call(this.log, String(text), fields)\n  }\n\n  // -------------------------------------------------------------------------\n  // app — snapshot only; worker reads app.* from the init message.\n  // Provide it here for completeness in case worker calls it post-init.\n  // -------------------------------------------------------------------------\n\n  private dispatchApp(_msg: BridgeCallMessage): unknown {\n    return this.opts.capabilityHost.appSnapshot()\n  }\n\n  // -------------------------------------------------------------------------\n  // i18n","sourceCodeStart":590,"sourceCodeEnd":626,"githubUrl":"https://github.com/agalwood/Motrix/blob/1a708ee57746c434e2c67a44bbf0906a976afea4/src/core/plugin/host/capability-bridge.ts#L590-L626","documentation":"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.","triggerScenarios":"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().","commonSituations":"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().","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."],"exampleFix":"// before\nlog.fatal('disk full')\n// after\nlog.error('disk full')","handlingStrategy":"type-guard","validationCode":"const KNOWN_LOG_METHODS = ['info','warn','error','debug','trace'] as const\nfunction isKnownLogMethod(m: string): boolean {\n  return (KNOWN_LOG_METHODS as readonly string[]).includes(m)\n}","typeGuard":"function isLogLevel(m: string): m is 'info'|'warn'|'error'|'debug'|'trace' {\n  return ['info','warn','error','debug','trace'].includes(m)\n}","tryCatchPattern":"try { (log as any)[method](msg, fields) }\ncatch (e) {\n  if (e instanceof Error && e.code === 'plugin.capability.unavailable') {\n    log.error(msg, fields) // downgrade to a known level\n    return\n  }\n  throw e\n}","preventionTips":["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."],"tags":["plugin","capability","log"],"backgroundTag":null,"analyzedSha":"1a708ee57746c434e2c67a44bbf0906a976afea4","analyzedAt":"2026-08-12T16:18:09.346Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}