n8n-io/n8n · error · Error
oldString not found in file: ${filePath}
Error message
oldString not found in file: ${filePath} What it means
Thrown by edit_file when oldString is not found as a substring of the file content. The file was successfully read and is under the size limit, but the exact text to replace does not exist in the file. This is a string-match failure, not a path or permission issue.
Source
Thrown at packages/@n8n/computer-use/src/tools/filesystem/edit-file.ts:41
await buildFilesystemResource(dir, filePath, 'filesystemRead', `Read file: ${filePath}`),
await buildFilesystemResource(dir, filePath, 'filesystemWrite', `Edit file: ${filePath}`),
];
},
async execute({ filePath, oldString, newString }, { dir }) {
const resolvedReadablePath = await resolveReadablePath(dir, filePath);
const resolvedWritablePath = await resolveSafePath(dir, filePath);
const stat = await fs.stat(resolvedReadablePath);
if (stat.size > MAX_FILE_SIZE) {
throw new Error(
`File too large: ${stat.size} bytes (max ${MAX_FILE_SIZE} bytes). Use write_file to replace the entire content.`,
);
}
const content = await fs.readFile(resolvedReadablePath, 'utf-8');
if (!content.includes(oldString)) {
throw new Error(`oldString not found in file: ${filePath}`);
}
await fs.writeFile(resolvedWritablePath, content.replace(oldString, newString), 'utf-8');
return formatCallToolResult({ path: filePath });
},
};
View on GitHub (pinned to 5ac6606e81)
Solutions
- Read the file first to copy the exact content for oldString
- Use a shorter, unique substring of the target text as oldString
- Check for whitespace, tab/space, and line-ending (CRLF/LF) differences
- Use write_file to replace the entire file if the edit is large or the content is uncertain
Example fix
// before (oldString doesn't match exactly):
await edit_file({ filePath: 'src/app.ts', oldString: 'function main()', newString: 'function main(config)' });
// after (read first, use exact text):
const content = await read_file({ filePath: 'src/app.ts' });
// copy the exact line including whitespace
await edit_file({ filePath: 'src/app.ts', oldString: 'function main() {', newString: 'function main(config) {' }); Defensive patterns
Strategy: validation
Validate before calling
import * as fs from 'node:fs/promises';
async function validateOldString(filePath: string, oldString: string): Promise<boolean> {
const content = await fs.readFile(filePath, 'utf-8');
return content.includes(oldString);
}
// Before calling edit_file:
if (!(await validateOldString(resolvedPath, oldString))) {
throw new Error('oldString not found. Read the file first to get exact text.');
} Type guard
function isOldStringNotFound(e: unknown): boolean {
return e instanceof Error && e.message.startsWith('oldString not found in file:');
} Prevention
- Always read the file before constructing oldString to get exact whitespace and content
- Use the shortest unique substring of the target text as oldString
- Be aware of tab vs space and CRLF vs LF differences when copying text
When it happens
Trigger: The oldString has different whitespace or indentation than the file, the content was already modified by a prior edit, line endings differ (CRLF vs LF), the oldString was paraphrased rather than copied verbatim, or the target content is in a different file.
Common situations: AI agent generates oldString from memory without reading the file first, or the file changed between read and edit, or tabs vs spaces mismatch.
Related errors
- File too large: ${stat.size} bytes (max ${MAX_FILE_SIZE} byt
- Access denied: "${excludedSegment}" is excluded from filesys
- File too large: ${stat.size} bytes (max ${MAX_FILE_SIZE} byt
- Unsupported binary file — only PNG, JPEG, GIF, WebP and PDF
- Pattern "${pattern}" escapes the base directory
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/6c39b6ffca243a9c.
Report an issue: GitHub.