can1357/oh-my-pi · error
replace_memory_files contains duplicate ${name}
Error message
replace_memory_files contains duplicate ${name} What it means
The `files` array must list each allowed memory file at most once. This error is thrown when a second entry repeats an already-seen valid memory file name, preventing ambiguous double-replacement.
Source
Thrown at packages/coding-agent/src/sharpshooter/consolidate.ts:254
}
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++) {
if (redacted.charCodeAt(index) === 10) lines += 1;
}
if (lines > SHARPSHOOTER_MAX_FILE_LINES) {
throw new Error(`${name} exceeds the ${SHARPSHOOTER_MAX_FILE_LINES}-line limit`);
}
files.push({ name, content: redacted });
}
const totalChars = files.reduce((sum, file) => sum + file.content.trim().length, 0);
if (totalChars === 0 && SHARPSHOOTER_MEMORY_FILES.some(name => currentFiles[name].trim().length > 0)) {
throw new Error("replace_memory_files returned all-empty content; refusing to wipe memory files");
}
return files;
}
View on GitHub (pinned to 9690622007)
Solutions
- Merge duplicate entries into one `content` string per file name.
- Keep only the final intended version of each file and drop earlier drafts.
- Retry the run if the duplicates came from flaky model output.
- If generating calls in code, dedupe by name before invoking.
Example fix
// before
{ files: [{name:"A.md",content:"x"},{name:"A.md",content:"y"}] }
// after
{ files: [{ name: "A.md", content: "x\ny" }] } Defensive patterns
Strategy: validation
Validate before calling
const names = files.map(f => f?.name);
if (new Set(names).size !== names.length) throw new Error("duplicate memory file names"); Type guard
null
Try / catch
try {
const files = parseReplacementFiles(call, currentFiles);
} catch (err) {
const m = String(err).match(/duplicate (.+)$/);
if (m) logger.warn(`duplicate entry for ${m[1]}; retrying`);
} Prevention
- Instruct the model: one entry per memory file.
- Dedupe by name in any code path that constructs the call.
- Prefer 'last entry wins' merge helpers in tests instead of emitting duplicates.
When it happens
Trigger: The model emits the same memory filename twice in one `replace_memory_files` call, e.g. two `AGENTS.md` entries with different content.
Common situations: Models regenerating a file after 'remembering' an earlier draft in the same call; streaming dedup failures; template prompts encouraging per-section entries with the same name.
Related errors
- Tool ${toolCall.name} not found
- Tool "${toolCall.name}" not found
- Validation failed for tool "${toolCall.name}": Tool call arg
- Validation failed for tool "${toolCall.name}":\n${errors}\n\
- replace_memory_files requires a files array
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/384320760b11d34e.
Report an issue: GitHub.