【Bug已解决】openclaw plugin load failed / TypeError Cannot read property name — OpenClaw 插件加载失败解决方案
·
【Bug已解决】openclaw: "Plugin load failed" / TypeError: Cannot read property 'name' of undefined — OpenClaw 插件加载失败解决方案
1. 问题描述
OpenClaw 在启动或运行过程中无法加载插件,报出类型错误:
# 插件加载失败 - 标准报错
$ openclaw "分析代码"
Error: Plugin load failed
TypeError: Cannot read property 'name' of undefined
# 插件入口找不到
$ openclaw --plugin custom-tools "task"
Error: Cannot find module './plugins/custom-tools'
plugin entry not found in plugin directory
# 插件 API 版本不兼容
$ openclaw "task"
Error: Plugin API version mismatch
Expected v3, got v1. Plugin 'code-formatter' is incompatible.
# 插件初始化崩溃
$ openclaw "task"
Error: Plugin 'test-runner' initialization failed
TypeError: openclaw.registerCommand is not a function
这个问题在以下场景中特别常见:
- 插件 API 版本与 OpenClaw 主程序不匹配
- 插件目录结构不符合规范
- 插件 manifest.json 缺少必要字段
- 插件代码中有语法错误或依赖缺失
- 插件加载顺序导致依赖未就绪
- 升级 OpenClaw 后旧插件 API 变更

2. 原因分析
核心原理拆解
OpenClaw 启动 → 扫描插件目录 → 读取 manifest.json
↓
验证 API 版本 ←──── 检查插件入口文件
↓
执行 plugin.init() ←──── 注入 API 对象
↓
init() 中访问未定义属性 → 抛出 TypeError
OpenClaw 插件加载机制说明
OpenClaw 的插件系统基于 manifest.json 描述符 + JavaScript 入口文件的架构。启动时,插件管理器会:
- 扫描
~/.openclaw/plugins/目录下的所有子目录 - 读取每个子目录中的
manifest.json文件 - 验证 manifest 中的
apiVersion是否与主程序兼容 - 根据 manifest 中的
entry字段加载入口 JS 文件 - 调用入口文件导出的
init(api)函数,传入 API 对象 - 插件通过
api.registerCommand()、api.registerTool()等方法注册功能
如果 manifest.json 缺少必要字段(如 name),入口文件不存在,或 init() 函数中访问了未注入的 API 方法,就会触发上述错误。
原因分类表
| 原因分类 | 具体表现 | 占比 |
|---|---|---|
| API 版本不兼容 | registerCommand is not a function | 约 30% |
| manifest 缺字段 | Cannot read property 'name' | 约 25% |
| 入口文件缺失 | Cannot find module | 约 20% |
| 依赖未安装 | Cannot find module 'xxx' | 约 15% |
| 加载顺序错误 | 依赖插件未初始化 | 约 5% |
| 语法错误 | Unexpected token | 约 5% |
3. 解决方案
方案一:验证并修复 manifest.json(最推荐)
# 步骤 1:查看插件目录结构
ls -la ~/.openclaw/plugins/
ls -la ~/.openclaw/plugins/*/
# 步骤 2:检查 manifest.json 是否存在且格式正确
for plugin in ~/.openclaw/plugins/*/; do
echo "=== $(basename $plugin) ==="
if [ -f "$plugin/manifest.json" ]; then
python3 -m json.tool "$plugin/manifest.json" 2>&1
else
echo "❌ manifest.json 不存在"
fi
echo ""
done
# 步骤 3:修复缺失字段
# 正确的 manifest.json 示例:
cat > ~/.openclaw/plugins/custom-tools/manifest.json << 'EOF'
{
"name": "custom-tools",
"version": "1.0.0",
"apiVersion": "3",
"entry": "./index.js",
"description": "自定义工具插件",
"author": "developer",
"dependencies": []
}
EOF
# 步骤 4:验证修复
openclaw --debug 2>&1 | grep -i "plugin\|manifest"
openclaw "测试"
方案二:修复 API 版本兼容性
# 步骤 1:查看 OpenClaw 当前版本和 API 版本
openclaw --version
openclaw --api-version
# 步骤 2:查看插件的 API 版本
cat ~/.openclaw/plugins/*/manifest.json | grep -i apiVersion
# 步骤 3:如果 API 版本不匹配,更新插件
# 方式1: 更新插件到兼容版本
cd ~/.openclaw/plugins/custom-tools/
npm update
# 方式2: 修改 manifest.json 中的 apiVersion
python3 -c "
import json
import os
plugin_dir = os.path.expanduser('~/.openclaw/plugins/custom-tools')
manifest_path = os.path.join(plugin_dir, 'manifest.json')
with open(manifest_path, 'r') as f:
manifest = json.load(f)
# 查看当前 API 版本
print(f'当前 apiVersion: {manifest.get(\"apiVersion\", \"未设置\")}')
# 更新为当前主程序兼容的版本
manifest['apiVersion'] = '3'
with open(manifest_path, 'w') as f:
json.dump(manifest, f, indent=4)
print('apiVersion 已更新为 3')
"
# 步骤 4:验证
openclaw --debug 2>&1 | grep -i "api.*version\|compat"
openclaw "测试"
方案三:修复入口文件和依赖
# 步骤 1:验证入口文件存在
PLUGIN_DIR=~/.openclaw/plugins/custom-tools
ENTRY=$(python3 -c "import json; print(json.load(open('$PLUGIN_DIR/manifest.json'))['entry'])")
echo "入口文件: $PLUGIN_DIR/$ENTRY"
if [ ! -f "$PLUGIN_DIR/$ENTRY" ]; then
echo "❌ 入口文件不存在,创建基本模板"
mkdir -p "$PLUGIN_DIR"
cat > "$PLUGIN_DIR/index.js" << 'JAVASCRIPT'
module.exports = {
init: function(api) {
// 注册自定义命令
api.registerCommand('custom', (args) => {
return 'Custom command executed: ' + args.join(' ');
});
// 注册工具
if (api.registerTool) {
api.registerTool('formatter', {
description: 'Format code',
execute: (input) => input.trim()
});
}
console.log('Plugin custom-tools loaded successfully');
},
destroy: function() {
console.log('Plugin custom-tools destroyed');
}
};
JAVASCRIPT
fi
# 步骤 2:安装插件依赖
cd "$PLUGIN_DIR"
if [ -f "package.json" ]; then
npm install
else
echo "无 package.json,跳过依赖安装"
fi
# 步骤 3:验证入口文件语法
node -c "$PLUGIN_DIR/index.js"
# 无输出 = 语法正确
# 步骤 4:测试加载
openclaw --debug 2>&1 | grep -i "plugin.*load\|plugin.*init"
openclaw "测试"
方案四:修复插件加载顺序
# 步骤 1:查看插件加载顺序
openclaw --debug 2>&1 | grep -i "plugin.*order\|plugin.*load" | head -20
# 步骤 2:检查插件间依赖关系
for plugin in ~/.openclaw/plugins/*/; do
name=$(basename "$plugin")
deps=$(python3 -c "
import json, sys
try:
m = json.load(open('$plugin/manifest.json'))
print(','.join(m.get('dependencies', [])))
except: print('')
" 2>/dev/null)
echo "$name → depends on: ${deps:-无}"
done
# 步骤 3:手动配置加载顺序
cat > ~/.openclaw/plugin-config.json << 'EOF'
{
"loadOrder": [
"core-utils",
"file-reader",
"code-formatter",
"test-runner",
"custom-tools"
],
"timeout": 5000,
"continueOnError": false
}
EOF
# 步骤 4:验证加载顺序
openclaw --debug 2>&1 | grep -i "plugin.*order"
openclaw "测试"
方案五:使用 --safe-mode 隔离问题插件
# 步骤 1:安全模式启动(禁用所有第三方插件)
openclaw --safe-mode "测试任务"
# 步骤 2:如果安全模式正常,逐个启用插件排查
openclaw --safe-mode --enable-plugin core-utils "测试"
openclaw --safe-mode --enable-plugin core-utils --enable-plugin file-reader "测试"
# 步骤 3:或批量禁用后逐个启用
openclaw --disable-all-plugins "测试"
# 启用单个插件测试
openclaw --enable-only custom-tools "测试"
# 步骤 4:找到问题插件后删除或修复
PLUGIN_NAME="custom-tools"
rm -rf ~/.openclaw/plugins/$PLUGIN_NAME/
# 或备份后修复
mv ~/.openclaw/plugins/$PLUGIN_NAME/ ~/.openclaw/plugins/$PLUGIN_NAME.bak/
# 步骤 5:验证
openclaw "测试"
方案六:编写插件兼容性检查工具
#!/usr/bin/env python3
"""OpenClaw 插件兼容性检查工具"""
import json
import os
import sys
import subprocess
class PluginChecker:
def __init__(self, plugin_dir=None):
self.plugin_dir = plugin_dir or os.path.expanduser('~/.openclaw/plugins')
self.errors = []
self.warnings = []
def get_api_version(self):
"""获取 OpenClaw 当前 API 版本"""
try:
result = subprocess.run(
['openclaw', '--api-version'],
capture_output=True, text=True, timeout=5
)
return result.stdout.strip()
except Exception:
return None
def check_manifest(self, plugin_path):
"""检查 manifest.json"""
manifest_path = os.path.join(plugin_path, 'manifest.json')
checks = {'valid': True, 'errors': [], 'warnings': []}
# 检查文件是否存在
if not os.path.exists(manifest_path):
checks['valid'] = False
checks['errors'].append('manifest.json 不存在')
return checks
# 检查 JSON 格式
try:
with open(manifest_path, 'r') as f:
manifest = json.load(f)
except json.JSONDecodeError as e:
checks['valid'] = False
checks['errors'].append(f'JSON 格式错误: {e}')
return checks
# 检查必要字段
required_fields = ['name', 'version', 'apiVersion', 'entry']
for field in required_fields:
if field not in manifest:
checks['valid'] = False
checks['errors'].append(f'缺少必要字段: {field}')
elif not manifest[field]:
checks['valid'] = False
checks['errors'].append(f'字段为空: {field}')
# 检查入口文件
if 'entry' in manifest:
entry_path = os.path.join(plugin_path, manifest['entry'])
if not os.path.exists(entry_path):
checks['valid'] = False
checks['errors'].append(f'入口文件不存在: {manifest["entry"]}')
else:
# 检查 JS 语法
result = subprocess.run(
['node', '-c', entry_path],
capture_output=True, text=True, timeout=5
)
if result.returncode != 0:
checks['valid'] = False
checks['errors'].append(f'入口文件语法错误: {result.stderr.strip()}')
# 检查 API 版本兼容性
current_api = self.get_api_version()
if current_api and 'apiVersion' in manifest:
if manifest['apiVersion'] != current_api:
checks['warnings'].append(
f'API 版本不匹配: 插件={manifest["apiVersion"]}, '
f'主程序={current_api}'
)
# 检查依赖
if 'dependencies' in manifest:
for dep in manifest['dependencies']:
dep_path = os.path.join(self.plugin_dir, dep)
if not os.path.exists(dep_path):
checks['warnings'].append(f'依赖插件不存在: {dep}')
return checks
def check_all(self):
"""检查所有插件"""
if not os.path.exists(self.plugin_dir):
print(f'插件目录不存在: {self.plugin_dir}')
return
plugins = [d for d in os.listdir(self.plugin_dir)
if os.path.isdir(os.path.join(self.plugin_dir, d))]
if not plugins:
print('未找到任何插件')
return
print(f'检查 {len(plugins)} 个插件...\n')
for plugin_name in sorted(plugins):
plugin_path = os.path.join(self.plugin_dir, plugin_name)
result = self.check_manifest(plugin_path)
status = '✅' if result['valid'] else '❌'
print(f'{status} {plugin_name}')
for err in result['errors']:
print(f' 错误: {err}')
self.errors.append(f'{plugin_name}: {err}')
for warn in result['warnings']:
print(f' 警告: {warn}')
self.warnings.append(f'{plugin_name}: {warn}')
print()
# 总结
print('=' * 50)
print(f'总计: {len(plugins)} 个插件')
print(f'错误: {len(self.errors)} 个')
print(f'警告: {len(self.warnings)} 个')
if self.errors:
print('\n需要修复的插件:')
for err in self.errors:
print(f' - {err}')
if __name__ == '__main__':
checker = PluginChecker()
checker.check_all()
4. 各方案对比总结
| 方案 | 适用场景 | 推荐指数 | 难度 |
|---|---|---|---|
| 方案一:修复 manifest | 缺字段 | ⭐⭐⭐⭐⭐ | 低 |
| 方案二:修复 API 版本 | 版本不兼容 | ⭐⭐⭐⭐⭐ | 中 |
| 方案三:修复入口文件 | 文件缺失 | ⭐⭐⭐⭐ | 中 |
| 方案四:修复加载顺序 | 依赖问题 | ⭐⭐⭐⭐ | 中 |
| 方案五:安全模式 | 隔离排查 | ⭐⭐⭐⭐⭐ | 低 |
| 方案六:检查工具 | 长期运维 | ⭐⭐⭐ | 高 |
5. 常见问题 FAQ
5.1 升级 OpenClaw 后所有插件都报错
OpenClaw 大版本升级可能引入 API breaking changes。查看变更日志确认 API 变化,批量更新所有插件的 apiVersion 和 API 调用方式。
# 查看变更日志
openclaw --changelog | head -100
# 批量更新 apiVersion
for manifest in ~/.openclaw/plugins/*/manifest.json; do
python3 -c "
import json
with open('$manifest', 'r') as f:
m = json.load(f)
m['apiVersion'] = '3'
with open('$manifest', 'w') as f:
json.dump(m, f, indent=4)
print(f'Updated: $manifest')
"
done
5.2 Windows 上插件路径问题
Windows 路径分隔符是 \,manifest.json 中的 entry 字段可能使用了错误的分隔符:
# 检查 manifest.json 中的 entry 路径
Get-Content ~/.openclaw/plugins/custom-tools/manifest.json | ConvertFrom-Json | Select-Object entry
# 确保使用正斜杠或双反斜杠
# 正确: "entry": "./index.js" 或 "entry": ".\\index.js"
# 错误: "entry": ".\index.js" (单反斜杠会被转义)
5.3 插件依赖的 npm 包未安装
插件入口文件 require() 了外部包但未安装:
# 进入插件目录安装依赖
cd ~/.openclaw/plugins/custom-tools/
npm install
# 或检查 package.json 依赖
cat package.json | python3 -m json.tool
# 批量安装所有插件依赖
for plugin in ~/.openclaw/plugins/*/; do
if [ -f "$plugin/package.json" ]; then
echo "Installing deps for $(basename $plugin)..."
cd "$plugin" && npm install --production
fi
done
5.4 插件 init() 中 API 对象为空
OpenClaw 注入的 API 对象可能在不同版本中有不同结构。使用可选链或防御性检查:
module.exports = {
init: function(api) {
// ❌ 错误写法:直接调用可能不存在的方法
// api.registerCommand('test', handler);
// ✅ 正确写法:先检查方法是否存在
if (api && typeof api.registerCommand === 'function') {
api.registerCommand('test', (args) => 'test: ' + args);
}
if (api && typeof api.registerTool === 'function') {
api.registerTool('formatter', { execute: (s) => s.trim() });
}
// 使用 API 版本号做兼容
const version = api?.version || 1;
if (version >= 3 && api.registerHook) {
api.registerHook('beforeSend', (ctx) => { /* ... */ });
}
}
};
5.5 多个插件注册了同名命令
两个插件注册了相同的命令名导致冲突:
# 查看命令冲突
openclaw --debug 2>&1 | grep -i "conflict\|duplicate"
# 在 manifest.json 中使用命名空间
{
"name": "custom-tools",
"namespace": "custom",
"commands": ["custom:format", "custom:lint"]
}
# 或在插件配置中设置优先级
cat > ~/.openclaw/plugin-config.json << 'EOF'
{
"commandPriority": {
"format": "code-formatter",
"lint": "custom-tools"
}
}
EOF
5.6 Docker 中插件目录未挂载
Docker 容器内插件目录是空的:
# 挂载宿主机插件目录到容器
docker run -it --rm \
-v ~/.openclaw/plugins:/root/.openclaw/plugins \
-v ~/.openclaw/config.json:/root/.openclaw/config.json \
openclaw-image
# 或在 Dockerfile 中 COPY 插件
COPY plugins/ /root/.openclaw/plugins/
# 验证
docker run --rm openclaw-image openclaw --list-plugins
5.7 插件加载超时
某些插件 init() 执行耗时操作导致超时:
# 调整插件加载超时
export OPENCLAW_PLUGIN_TIMEOUT=30000 # 30秒
# 或在配置中设置
python3 -c "
import json
with open(os.path.expanduser('~/.openclaw/plugin-config.json'), 'r') as f:
config = json.load(f)
config['timeout'] = 30000
config['asyncInit'] = True # 允许异步初始化
with open(os.path.expanduser('~/.openclaw/plugin-config.json'), 'w') as f:
json.dump(config, f, indent=2)
print('超时和异步初始化已配置')
"
# 在插件中使用异步初始化
# index.js
module.exports = {
init: async function(api) {
await loadLargeDataset();
api.registerCommand('search', (args) => search(args));
}
};
5.8 如何查看已加载的插件列表
# 列出所有已安装插件
openclaw --list-plugins
# 查看插件详细信息
openclaw --plugin-info custom-tools
# 查看插件加载日志
openclaw --debug 2>&1 | grep -i "plugin"
5.9 插件内存泄漏
插件未正确实现 destroy() 方法导致内存泄漏:
// 确保插件有 destroy 方法
module.exports = {
init: function(api) {
this.timer = setInterval(() => { /* ... */ }, 1000);
api.registerCommand('start', () => this.timer.start());
},
destroy: function() {
// 清理定时器、事件监听器等
if (this.timer) {
clearInterval(this.timer);
}
console.log('Plugin cleaned up');
}
};
# 检查插件内存使用
openclaw --debug --profile-plugins 2>&1 | grep -i "memory\|leak"
5.10 排查清单速查表
□ 1. 检查 manifest.json 是否存在且格式正确
□ 2. 确认 name/version/apiVersion/entry 字段完整
□ 3. 验证入口文件路径存在
□ 4. node -c 检查入口文件语法
□ 5. openclaw --api-version 对比插件 apiVersion
□ 6. 检查插件 npm 依赖是否安装
□ 7. openclaw --safe-mode 隔离问题插件
□ 8. openclaw --debug 查看加载顺序
□ 9. 检查插件间依赖关系
□ 10. 确认 init() 中 API 方法做了存在性检查
6. 总结
- 根本原因:插件加载失败最常见原因是 API 版本不兼容(30%)和 manifest.json 缺字段(25%)
- 最佳实践:使用
openclaw --debug 2>&1 | grep plugin诊断具体加载步骤 - manifest 修复:确保
name、version、apiVersion、entry四个字段完整且值有效 - 安全模式:使用
openclaw --safe-mode快速隔离问题插件,再逐个启用排查 - 最佳实践建议:编写插件时对 API 方法做防御性检查(
typeof api.registerCommand === 'function'),并始终实现destroy()方法避免内存泄漏
故障排查流程图
flowchart TD
A[插件加载失败] --> B[检查 manifest.json]
B --> C[python3 -m json.tool 验证]
C --> D{格式正确?}
D -->|否| E[修复 JSON 格式]
D -->|是| F[检查必要字段]
E --> G[重新加载测试]
F --> H{name/version/apiVersion/entry 齐全?}
H -->|否| I[补充缺失字段]
H -->|是| J[验证入口文件]
I --> G
J --> K{入口文件存在?}
K -->|否| L[创建入口文件]
K -->|是| M[node -c 检查语法]
L --> G
M --> N{语法正确?}
N -->|否| O[修复语法错误]
N -->|是| P[检查 API 版本]
O --> G
P --> Q{版本兼容?}
Q -->|否| R[更新 apiVersion]
Q -->|是| S[检查依赖]
R --> G
S --> T{依赖就绪?}
T -->|否| U[npm install]
T -->|是| V[安全模式测试]
U --> G
V --> W{安全模式正常?}
W -->|是| X[逐个启用排查]
W -->|否| Y[检查核心配置]
X --> Z[找到问题插件]
Z --> AA[修复或移除]
AA --> G
G --> BB{加载成功?}
BB -->|是| CC[✅ 问题解决]
BB -->|否| DD[使用兼容性检查工具]
DD --> CC
更多推荐

所有评论(0)