can1357/oh-my-pi · error
replace_memory_files requires a files array
Error message
replace_memory_files requires a files array
What it means
parseReplacementFiles validates the arguments of the single `replace_memory_files` tool call that sharpshooter consolidation requires. This error is thrown when the call's arguments are missing, not a plain object, or lack an array-valued `files` field. It guards the downstream per-entry validation loop which assumes `args.files` is an array.
Source
Thrown at packages/coding-agent/src/sharpshooter/consolidate.ts:240
}
return truncateApproxTokens(blocks.join("\n\n"), PROJECT_DOC_TOKEN_LIMIT);
}
function parseReplacementFiles(
content: readonly unknown[],
currentFiles: Readonly<Record<SharpshooterMemoryFile, string>>,
): ReplacementFile[] {
const toolCalls = content.filter(
(block): block is { type: "toolCall"; name: string; arguments: unknown } =>
typeof block === "object" && block !== null && "type" in block && block.type === "toolCall",
);
if (toolCalls.length !== 1 || toolCalls[0]?.name !== replaceMemoryFilesTool.name) {
throw new Error("sharpshooter consolidation must call replace_memory_files exactly once");
}
const args = toolCalls[0].arguments;
if (!args || typeof args !== "object" || !("files" in args) || !Array.isArray(args.files)) {
throw new Error("replace_memory_files requires a files array");
}
const seen = new Set<SharpshooterMemoryFile>();
const files: ReplacementFile[] = [];
for (const item of args.files) {
if (!item || typeof item !== "object" || !("name" in item) || !("content" in item)) {
throw new Error("replace_memory_files contains an invalid file entry");
}
const name = item.name;
const rawContent = item.content;
if (!isMemoryFileName(name) || typeof rawContent !== "string") {
throw new Error("replace_memory_files contains an invalid file entry");
}
if (seen.has(name)) throw new Error(`replace_memory_files contains duplicate ${name}`);
seen.add(name);
const redacted = redactSecrets(rawContent);
let lines = redacted.length > 0 ? 1 : 0;
for (let index = 0; index + 1 < redacted.length; index++) {View on GitHub (pinned to 9690622007)
Solutions
- Ensure the model call forces a strict tool schema so `files` is always an array (toolChoice required plus a JSON-schema-typed tool definition).
- Check the raw tool-call arguments in the response to see what shape was actually emitted.
- Retry the consolidation run; malformed arguments from an LLM are usually transient.
- If integrating programmatically, pass `{ files: [{ name, content }, ...] }` with `files` as an array.
Example fix
// before: args shaped as an object map
replace_memory_files({ "AGENTS.md": "..." })
// after: files must be an array of {name, content}
replace_memory_files({ files: [{ name: "AGENTS.md", content: "..." }] }) Defensive patterns
Strategy: type-guard
Validate before calling
function hasFilesArray(args: unknown): args is { files: unknown[] } {
return !!args && typeof args === "object" && "files" in args && Array.isArray((args as { files?: unknown }).files);
} Type guard
const isFilesArgs = (a: unknown): a is { files: Array<{ name: string; content: string }> } =>
typeof a === "object" && a !== null && Array.isArray((a as any).files); Try / catch
try {
const files = parseReplacementFiles(toolCall, currentFiles);
} catch (err) {
logger.warn("invalid replace_memory_files arguments; skipping consolidation", { err });
} Prevention
- Enforce a JSON schema on the tool definition so `files` must be an array.
- Include a usage example in the tool description.
- Validate model output before acting on it.
When it happens
Trigger: The LLM calls `replace_memory_files` with no arguments object, with `files` absent, or with `files` set to a non-array value (e.g. an object keyed by filename, or a string).
Common situations: Model schema drift or weak tool-calling models emitting malformed arguments; hand-crafted or replayed tool calls in tests; a prompt change causing the model to pass files as a map instead of an array.
Related errors
- Validation failed for tool "${toolCall.name}":\n${errors}\n\
- replace_memory_files contains an invalid file entry
- Tool ${toolCall.name} not found
- anthropic-messages: ${data.summary}
- Schema contains a circular object graph — cannot enforce str
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/31cc35da97e54604.
Report an issue: GitHub.