chatboxai/chatbox · error · Error
invalid file entry for "${name}"
Error message
invalid file entry for "${name}" What it means
Thrown by prepareSnapshotFiles when iterating a remote skill's files list and encountering an entry that is not a non-null object with string path AND string content. It is the schema validation gate before any filesystem path resolution; a single malformed entry aborts the whole snapshot write.
Source
Thrown at src/main/skills/builtin-sync.ts:176
const normalized = path.normalize(relativePath)
// 顶层保留文件大小写不敏感比较:case-insensitive 文件系统(macOS/Windows)上
// "skill.md" 与生成的 "SKILL.md" 指向同一文件,若放行会覆盖 frontmatter+body。
const lower = normalized.toLowerCase()
if (normalized === '.' || lower === 'skill.md' || lower === 'source.json') return null
if (normalized.startsWith('..') || path.isAbsolute(normalized)) return null
const target = path.resolve(skillDir, normalized)
const root = path.resolve(skillDir)
if (target !== root && !target.startsWith(root + path.sep)) return null
return { target, normalizedPath: normalized.split(path.sep).join('/') }
}
function prepareSnapshotFiles(name: string, skillDir: string, files: RemoteSkillFile[]): SnapshotFileTarget[] {
const targets: SnapshotFileTarget[] = []
const seenPaths = new Set<string>()
for (const file of files) {
if (!file || typeof file.path !== 'string' || typeof file.content !== 'string') {
throw new Error(`invalid file entry for "${name}"`)
}
const resolved = resolveSnapshotFilePath(skillDir, file.path)
if (!resolved) {
throw new Error(`invalid file path for "${name}": ${file.path}`)
}
if (seenPaths.has(resolved.normalizedPath)) {
throw new Error(`duplicate file path for "${name}": ${resolved.normalizedPath}`)
}
seenPaths.add(resolved.normalizedPath)
targets.push({ file, target: resolved.target, normalizedPath: resolved.normalizedPath })
}
return targets
}
/** 将 skill 内容写入快照目录的 SKILL.md(frontmatter + body)和附属文件,与 parser 的解析格式一致。 */
function writeSnapshotSkill(
name: string,
metadata: SkillMetadata,View on GitHub (pinned to 81571269ad)
Solutions
- Verify the server returns files as {path: string, content: string} per RemoteSkillFile; align client and server versions.
- If a malformed entry should be skippable, filter before prepareSnapshotFiles rather than letting it abort the sync.
- Add a runtime schema check (zod/ajv) on the fetched payload to fail with a precise message naming the bad field.
- Log the offending entry (without content) to identify which remote skill is malformed.
Example fix
// before
if (!file || typeof file.path !== 'string' || typeof file.content !== 'string') throw new Error(`invalid file entry for "${name}"`)
// after: skip bad entries and warn
if (!file || typeof file.path !== 'string' || typeof file.content !== 'string') { log.warn(`invalid file entry for "${name}": ${JSON.stringify({ ...file, content: undefined })}`); continue } Defensive patterns
Strategy: type-guard
Validate before calling
const valid = files.every((f): f is RemoteSkillFile => !!f && typeof f.path === 'string' && typeof f.content === 'string')
if (!valid) throw new Error(`invalid file entry for "${name}"`) Type guard
function isRemoteSkillFile(f: unknown): f is RemoteSkillFile {
return !!f && typeof (f as any).path === 'string' && typeof (f as any).content === 'string'
} Try / catch
try { await syncSkill(name, files) } catch (e) { if (/invalid file entry/.test((e as Error).message)) { log.warn(`remote skill '${name}' has malformed files; skipping`); return } throw e } Prevention
- Validate the RemoteSkillFile shape (zod/ajv) at the fetch boundary.
- Keep client and server versions in sync for the payload schema.
- Filter malformed entries instead of aborting the whole skill if partial sync is acceptable.
When it happens
Trigger: RemoteSkillFile payload from the server contains an entry where path or content is missing/number/null, or the entry itself is null/undefined. Triggered during skill snapshot sync (builtin-sync) when materializing remote skill files on disk.
Common situations: Backend schema regression returning {path, contentBase64} instead of {path, content}; partial/truncated fetch; a server-side null for an optional field mistakenly placed inside the files array; client/server version mismatch on the RemoteSkillFile shape.
Related errors
- invalid file path for "${name}": ${file.path}
- duplicate file path for "${name}": ${resolved.normalizedPath
- Session attachment ${id} not found
- Only failed session attachments can be retried
- Attachment content not found or empty
AI-assisted analysis of chatboxai/chatbox@81571269ad (2026-08-12).
Data as JSON: /api/errors/688c8d0daac720f9.
Report an issue: GitHub.