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

  1. Verify the server returns files as {path: string, content: string} per RemoteSkillFile; align client and server versions.
  2. If a malformed entry should be skippable, filter before prepareSnapshotFiles rather than letting it abort the sync.
  3. Add a runtime schema check (zod/ajv) on the fetched payload to fail with a precise message naming the bad field.
  4. 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

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


AI-assisted analysis of chatboxai/chatbox@81571269ad (2026-08-12). Data as JSON: /api/errors/688c8d0daac720f9. Report an issue: GitHub.