can1357/oh-my-pi · error
replace_memory_files returned all-empty content; refusing to
Error message
replace_memory_files returned all-empty content; refusing to wipe memory files
What it means
A safety guard against data loss: if every replacement file's content is empty/whitespace while at least one current memory file has non-empty content, consolidation is refused so the model cannot accidentally wipe accumulated memory. Thrown after all per-file validation passes but the aggregate total trimmed character count is zero.
Source
Thrown at packages/coding-agent/src/sharpshooter/consolidate.ts:268
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;
}
function isMemoryFileName(value: unknown): value is SharpshooterMemoryFile {
return typeof value === "string" && (SHARPSHOOTER_MEMORY_FILES as readonly string[]).includes(value);
}
async function applyReplacementFiles(bankDir: string, files: readonly ReplacementFile[]): Promise<void> {
const staged = files.map(file => ({
...file,
tempPath: path.join(bankDir, `.${file.name}.${process.pid}.${crypto.randomUUID()}.tmp`),
}));
try {
await Promise.all(staged.map(file => Bun.write(file.tempPath, file.content)));
for (const file of staged) await fs.rename(file.tempPath, path.join(bankDir, file.name));
} finally {
await Promise.all(staged.map(file => fs.rm(file.tempPath, { force: true }).catch(() => {})));View on GitHub (pinned to 9690622007)
Solutions
- Re-run consolidation so the model produces real summaries.
- If clearing memory is genuinely intended, clear files via the normal file tools rather than replace_memory_files.
- Check the upstream model response for truncation that emptied the content fields.
- Ensure the prompt instructs the model to always summarize, never blank, memory files.
Example fix
// before
{ files: [{ name: "AGENTS.md", content: "" }] }
// after
{ files: [{ name: "AGENTS.md", content: "- project: TS monorepo\n- test: bun test" }] } Defensive patterns
Strategy: validation
Validate before calling
const nonEmpty = files.some(f => f.content.trim().length > 0);
if (!nonEmpty && Object.values(currentFiles).some(c => c.trim().length > 0)) {
throw new Error("refusing to wipe non-empty memory");
} Type guard
null
Try / catch
try {
await consolidate();
} catch (err) {
if (String(err).includes("all-empty content")) {
logger.warn("consolidation produced empty memory; preserving existing files");
}
} Prevention
- Prompt the model to always write a meaningful summary, never blanks.
- Confirm truncation isn't emptying streamed content fields.
- Use explicit file-management tools (not replace_memory_files) when clearing memory intentionally.
When it happens
Trigger: The model calls `replace_memory_files` with `""` or whitespace-only `content` for every file during consolidation.
Common situations: Model deciding memory is stale and emitting empty files; truncation bugs producing empty strings; prompt confusion about how to clear memory.
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/5931562cdc327bda.
Report an issue: GitHub.