windmill-labs/windmill · error
Diff at index ${index}: old_string "${old_string}" not found
Error message
Diff at index ${index}: old_string "${old_string}" not found in code What it means
Diffs are applied sequentially with String.replace against the evolving script code. If a diff's old_string does not occur in the current (partially patched) code, the tool throws, naming the diff index and the unmatched string.
Source
Thrown at frontend/src/lib/components/copilot/chat/script/core.ts:806
content: 'Invalid diffs provided',
error: 'Diffs parameter is required and must be an array'
})
throw new Error('Diffs parameter is required and must be an array')
}
toolCallbacks.setToolStatus(toolId, { content: 'Applying code changes...' })
try {
// Save old code
const oldCode = scriptOptions.code
// Apply diffs sequentially
let updatedCode = oldCode
for (const [index, diff] of args.diffs.entries()) {
const { old_string, new_string, replace_all = false } = diff
if (!updatedCode.includes(old_string)) {
throw new Error(`Diff at index ${index}: old_string "${old_string}" not found in code`)
}
if (replace_all) {
updatedCode = updatedCode.replaceAll(old_string, new_string)
} else {
updatedCode = updatedCode.replace(old_string, new_string)
}
}
// Apply the code changes directly
await helpers.applyCode(updatedCode, { applyAll: true, mode: 'apply' })
// Show revert mode
await helpers.applyCode(oldCode, { mode: 'revert' })
toolCallbacks.setToolStatus(toolId, {
content: `Code changes applied`,
result: 'Success'View on GitHub (pinned to e474e8803c)
Solutions
- Re-read the current script code and regenerate diffs whose old_string exactly matches it (exact whitespace and indentation)
- Split large edits into smaller, uniquely-anchored diffs applied in order
- Ensure earlier diffs in the array don't consume the text a later old_string expects
- If replace was intended for all occurrences, set replace_all: true and confirm old_string matches every intended site
Example fix
// before — indentation mismatch
{ old_string: 'if (x) {\nreturn 1', new_string: '...' } // not found
// after — exact match from current code
{ old_string: '\tif (x) {\n\t\treturn 1', new_string: '...' } Defensive patterns
Strategy: validation
Validate before calling
const missing = diffs.findIndex(d => !updatedCode.includes(d.old_string))
if (missing !== -1) {
// re-read current code and regenerate diff at index `missing`
} Try / catch
try {
applyDiffs(code, diffs)
} catch (e) {
if (/not found in code/.test(e.message)) {
// re-fetch current script code, rebuild exact old_string, retry once
}
} Prevention
- Copy old_string verbatim from the current editor content including whitespace
- Sequence diffs so earlier replacements don't consume later old_strings
- Keep diffs small and anchored to unique snippets
When it happens
Trigger: old_string doesn't byte-match the editor code — wrong whitespace/indentation, stale code (editor changed since the model read it), the string was already replaced by an earlier diff in the same batch, or the model hallucinated the snippet.
Common situations: Model quoting normalized/fuzzy-matched code instead of exact text; consecutive diffs whose earlier replacement altered text a later diff expected; editing a script whose saved version differs from what the model saw.
Related errors
- Diffs parameter is required and must be an array
- Database path not provided
- Failed to apply code changes: ${errorMessage}
- Code parameter is required and must be a string
- result.substring(__RESULT_ERR_PREFIX.length)
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/40f0e4ddc58216ad.
Report an issue: GitHub.