can1357/oh-my-pi · error · Error

Operation ${operationNumber} did not match ${path}: your lin

Error message

Operation ${operationNumber} did not match ${path}: your lines match individually at lines ${separated.locations.join(", ")} but are not consecutive.
Copy-ready corrected operation:
${operationPayload(operation, operation.all ? "*" : "", separated.correctedPattern)}
${replacementGuidance}

What it means

The pattern's individual lines each match somewhere in the file, but the matched locations are not consecutive, so no single ordered region satisfies the whole pattern. The library detects this specific failure (via `nonConsecutiveGuidance`) and throws an error that includes a copy-ready corrected pattern with proper `...` gaps and guidance about the span the rewrite will replace.

Source

Thrown at packages/coding-agent/src/edit/sloppy.ts:2500

	// Sibling-claim disambiguation: an ambiguous op whose extra candidates are
	// already claimed by other operations' planned edits resolves to the free
	// one. Only ever narrows; all-excluded keeps the ambiguity diagnosis.
	if (exclusions !== undefined && candidates.length > 1) {
		const free = candidates.filter(
			candidate => !exclusions.some(claim => candidate.matchStart < claim.end && claim.start < candidate.matchEnd),
		);
		if (free.length > 0) candidates = free;
	}
	if (operation.all && candidates.length > 0) return candidates;
	if (candidates.length === 1) return [candidates[0]];
	if (candidates.length === 0) {
		const separated = nonConsecutiveGuidance(content, operation);
		if (separated) {
			const replacementGuidance =
				operation.rewrite.kind === "explicit"
					? `The REWRITE then replaces the whole span lines ${separated.locations[0]}-${separated.locations.at(-1)}, including the skipped lines — re-emit kept gaps with ${GAP}.`
					: `The inline replacements then target the whole span lines ${separated.locations[0]}-${separated.locations.at(-1)}, including skipped lines — re-emit kept gaps with ${GAP}.`;
			throw new Error(
				[
					`Operation ${operationNumber} did not match ${path}: your lines match individually at lines ${separated.locations.join(", ")} but are not consecutive.`,
					"Copy-ready corrected operation:",
					operationPayload(operation, operation.all ? "*" : "", separated.correctedPattern),
					replacementGuidance,
				].join("\n"),
			);
		}
		const guidance = noMatchGuidance(content, normalized, pattern, operation);
		throw new Error(
			[
				operation.all
					? `Operation ${operationNumber} ${OPENER}* found 0 matches in ${path}. ${guidance.reason}`
					: `Operation ${operationNumber} did not match ${path}. ${guidance.reason}`,
				"Current file content near the closest match (no re-read needed):",
				numberedPreview(content, guidance.previewOffset),
				"Copy-ready corrected operation:",
				operationPayload(operation, operation.all ? "*" : "", guidance.correctedPattern),

View on GitHub (pinned to 9690622007)

Solutions

  1. Use the copy-ready corrected operation included in the error — it inserts `...` between the non-adjacent lines.
  2. Re-read the region and rebuild the pattern from the actual consecutive lines.
  3. If the skipped lines are fine to leave, keep them under a `...` gap and note the REWRITE/inline replacement covers the whole span, so re-emit kept lines explicitly.

Example fix

// before
const pattern = "const a = 1;\nconst c = 3;"; // b exists between them
// after
const pattern = "const a = 1;\n...\nconst c = 3;";
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify the pattern lines are consecutive in the file before applying:
const idxs = patternLines.filter(l => l.trim()).map(l => {
  const i = content.split("\n").findIndex(f => f === l);
  return i;
});
const consecutive = idxs.every((v, k) => k === 0 || v === idxs[k - 1] + 1);
if (!consecutive) throw new Error("pattern lines are not consecutive; add ... between them");

Try / catch

try {
  await applySloppyEdit({ pattern });
} catch (err) {
  if (err instanceof Error && err.message.includes("not consecutive")) {
    // use the copy-ready corrected operation printed in the error message
    const corrected = extractCorrectedPattern(err.message);
    return applySloppyEdit({ pattern: corrected });
  }
  throw err;
}

Prevention

When it happens

Trigger: Writing a multi-line pattern where lines appear in the file but with other code between them (order preserved but not adjacent), e.g. assuming two statements are neighbors when an intervening line exists. Detected when `collectCandidates` finds zero matches but individual line searches succeed at separated locations.

Common situations: Reconstructing code from memory instead of the actual file; lines separated by a blank line, comment, or an edited statement; copying lines from different parts of a function into one pattern.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/85d3f7f3d4db6298. Report an issue: GitHub.