chatboxai/chatbox · warning · Error
Skill name and script name are required
Error message
Skill name and script name are required
What it means
Thrown by the skills:execute-script IPC handler when skillName or scriptName is falsy (empty string, undefined, null). This is the first guard before any filesystem access, validating that the renderer sent both required identifiers. The handler signature types them as string, but IPC payloads cross the trust boundary and are not guaranteed to match the declared type.
Source
Thrown at src/main/skills/ipc-handlers.ts:174
await shell.openPath(skillsDir)
return { success: true }
} catch (error) {
log.error('skills:open-directory failed', error)
return { success: false, error: error instanceof Error ? error.message : 'Unknown error' }
}
})
ipcMain.handle(
'skills:execute-script',
async (
_event,
params: { skillName: string; scriptName: string; args?: string[] }
): Promise<{ success: boolean; stdout: string; stderr: string; exitCode: number | null }> => {
const { skillName, scriptName, args = [] } = params
try {
if (!skillName || !scriptName) {
throw new Error('Skill name and script name are required')
}
if (skillName.includes('..') || skillName.includes('/') || skillName.includes('\\')) {
throw new Error('Invalid skill name: path traversal not allowed')
}
if (scriptName.includes('..') || scriptName.includes('/') || scriptName.includes('\\')) {
throw new Error('Invalid script name: path traversal not allowed')
}
const skillsDir = getSkillsDir()
const scriptPath = path.join(skillsDir, skillName, 'scripts', scriptName)
if (!fs.existsSync(scriptPath)) {
throw new Error(`Script not found: ${scriptName}`)
}
const resolvedSkillsDir = fs.realpathSync(skillsDir)
const resolvedScriptPath = fs.realpathSync(scriptPath)
if (!resolvedScriptPath.startsWith(`${resolvedSkillsDir}${path.sep}`)) {View on GitHub (pinned to 81571269ad)
Solutions
- Inspect the IPC call site in the renderer to confirm both skillName and scriptName are non-empty strings before invoking.
- Add a defensive guard in the renderer that disables the run button when either field is empty.
- If using a custom integration, validate the params object shape against the handler's expected type before send.
Example fix
// before
if (!skillName || !scriptName) {
throw new Error('Skill name and script name are required')
}
// renderer-side guard
if (!skillName?.trim() || !scriptName?.trim()) {
showToast('Skill name and script name are required')
return
}
await window.electron.ipcRenderer.invoke('skills:execute-script', { skillName, scriptName, args }) Defensive patterns
Strategy: validation
Validate before calling
function validateExecuteScriptParams(params: unknown): params is { skillName: string; scriptName: string; args?: string[] } {
if (!params || typeof params !== 'object') return false
const p = params as any
return typeof p.skillName === 'string' && p.skillName.trim().length > 0
&& typeof p.scriptName === 'string' && p.scriptName.trim().length > 0
&& (p.args === undefined || Array.isArray(p.args))
}
if (!validateExecuteScriptParams(params)) throw new Error('Invalid params') Type guard
function hasRequiredFields(p: unknown): p is { skillName: string; scriptName: string } {
return typeof (p as any)?.skillName === 'string' && !!((p as any).skillName).trim()
&& typeof (p as any)?.scriptName === 'string' && !!((p as any).scriptName).trim()
} Try / catch
ipcRenderer.invoke('skills:execute-script', params).then((res) => {
if (!res.success) showError(res.stderr)
})
// handler already catches internally and returns { success: false, stderr: message } Prevention
- Disable the run-script UI button when skillName or scriptName is empty.
- Validate the IPC payload shape in the renderer before invoking.
- Treat IPC params as untyped at the boundary — never trust the declared TS type.
When it happens
Trigger: The renderer invokes ipcRenderer.invoke('skills:execute-script', { skillName: '', scriptName: 'foo.sh' }) or omits scriptName entirely. Happens with malformed IPC calls, a stale renderer bundle whose payload shape changed, or a bug in the calling code that constructs the params object.
Common situations: A skill card UI sends an empty skillName because the selected skill was uninstalled between render and click; a plugin/script-runner integration passes undefined because it reads from an optional field; version skew between main and renderer after a partial update.
Related errors
- Invalid skill name: path traversal not allowed
- Invalid script name: path traversal not allowed
- Script not found: ${scriptName}
- invalid file entry for "${name}"
- invalid file path for "${name}": ${file.path}
AI-assisted analysis of chatboxai/chatbox@81571269ad (2026-08-12).
Data as JSON: /api/errors/b655b7d13df258ac.
Report an issue: GitHub.