can1357/oh-my-pi · error · Error
[${path}]: ${error.message}\nNo files were modified — sectio
Error message
[${path}]: ${error.message}\nNo files were modified — sections apply atomically. What it means
When a multi-file section-edit (sloppy edit) fails to apply a section to one file, the tool re-throws it wrapped with the file path and a note that the operation is atomic: no files from the batch were written. The wrapper preserves the original apply error (e.g. section not found, ambiguous match) and adds which file failed.
Source
Thrown at packages/coding-agent/src/edit/sloppy.ts:3959
if (!isEnoent(strippedError)) throw strippedError;
}
}
}
enforcePlanModeWrite(session, path);
const rawContent = await readEditFileText(absolutePath, path);
const { bom, text: fileText } = stripBom(rawContent);
const originalEnding = detectLineEnding(fileText);
const normalizedContent = normalizeToLF(fileText);
const notes: string[] = [];
let newContent: string;
try {
newContent = applySloppy(normalizedContent, normalizeToLF(section.body), { path, notes });
} catch (error) {
if (!(error instanceof Error) || !multiFile) throw error;
throw new Error(`[${path}]: ${error.message}\nNo files were modified — sections apply atomically.`);
}
if (newContent === normalizedContent) {
throw new Error(`Edits to ${path} resulted in no changes being made.`);
}
prepared.push({ path, absolutePath, rawContent, bom, originalEnding, normalizedContent, newContent, notes });
}
// Phase 2 — write every prepared section; only the last write flushes the LSP batch.
const perFileResults: EditToolPerFileResult[] = [];
const contentTexts: string[] = [];
let singleResult: EditResult | undefined;
let firstChangedLine: number | undefined;
for (let index = 0; index < prepared.length; index++) {
const entry = prepared[index];
const isLast = index === prepared.length - 1;
const sectionBatch: LspBatchRequest | undefined = batchRequest
? { id: batchRequest.id, flush: isLast && batchRequest.flush }
: undefined;View on GitHub (pinned to 9690622007)
Solutions
- Read the target file fresh and verify the section heading/body matches exactly
- Apply sections one file at a time to identify the failing section
- Fix the section body/heading in the tool call to match the current file content
- If the section was intentionally unchanged, remove it from the batch
Example fix
// before: section body guessed, no match
edit sections: [{ heading: '## Usage', body: 'stale text' }]
// after: re-read file, copy exact heading/body
const src = await Bun.file(path).text();
edit sections: [{ heading: '## Usage', body: extractCurrentBody(src) }] Defensive patterns
Strategy: validation
Validate before calling
const src = await Bun.file(path).text();
if (!src.includes(section.heading)) throw new Error(`heading ${section.heading} not in ${path}`); Type guard
function isSectionPresent(file: string, heading: string): boolean { return file.includes(heading); } Try / catch
try { await editSections(files) } catch (e) { if (/No files were modified/.test(e.message)) { /* re-read files, fix failing section named in [path] */ } else throw e } Prevention
- Re-read files immediately before multi-file edits
- Keep section headings byte-exact (no smart quotes/trailing spaces)
- Test each section against one file before batching
- Avoid editing the same file twice in one batch
When it happens
Trigger: Calling the multi-file section edit tool when applySloppy() throws for a given path — typically because a section heading/body in the requested content does not match the file (or a prior section's edits shifted content). Only thrown when multiFile is true; single-file edits rethrow the raw error.
Common situations: LLM-generated section content that doesn't exactly match an existing heading; stale file content from a previous read; applying sections to multiple files where one file was renamed or restructured; BOM/line-ending mismatch after normalization.
Related errors
- oldText must not be empty.
- Found ${occurrences} occurrences${pathSuffix}${moreMsg}:\n\n
- ${message} || Unable to read ${sectionPath}
- Missing hashline snapshot tag for ${sectionPath}; use `${HL_
- Multiple hashline sections resolve to the same file (${previ
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/cdb1e7f9bf4adba5.
Report an issue: GitHub.