can1357/oh-my-pi · error · Error

Operation ${operationNumber} has ${pattern.selectionRanges.l

Error message

Operation ${operationNumber} has ${pattern.selectionRanges.length} selections, but REWRITE proves neither positional substitution nor whole-span replacement.
Copy-ready per-selection interpretation:
${header}
${operation.patternText}
${REWRITE_HEADER}
${repeated.join("\n")}
Copy-ready whole-span interpretation:
${header}
${operation.patternText}
${REWRITE_HEADER}
${rewriteSelectionSpans(content, candidate, repeated)}

What it means

When a pattern has multiple selections, REWRITE must provably mean one of two things: per-selection substitution (the rewrite text is the replacement for each selection) or whole-span replacement (the rewrite replaces the entire matched span, verifiable against candidate content). If rewriteProvesWholeSpan fails for every candidate and positional substitution does not apply, the library throws a diagnostic containing two fully copy-ready alternative payloads — one per-selection, one whole-span — so the author can pick the intended interpretation.

Source

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

					lastMatchOffset = candidate.matchStart;
				}
				if (positionalChanges === 0) {
					const hint = positionalWouldChangeHint(content, candidates[0], pattern, segments);
					throwNoOp(
						operationNumber,
						{ content, offset: candidates[0].matchStart },
						operation.all ? candidates.length : undefined,
						hint,
					);
				}
				continue;
			}
			if (!candidates.every(candidate => rewriteProvesWholeSpan(content, candidate, baseResolvedRewrite))) {
				const candidate = candidates[0];
				const oneLineRewrite = baseResolvedRewrite.replace(/\s*\n\s*/gu, " ");
				const repeated = new Array<string>(pattern.selectionRanges.length).fill(oneLineRewrite);
				const header = operation.all ? `${OPENER}*` : OPENER;
				throw new Error(
					[
						`Operation ${operationNumber} has ${pattern.selectionRanges.length} selections, but REWRITE proves neither positional substitution nor whole-span replacement.`,
						"Copy-ready per-selection interpretation:",
						`${header}\n${operation.patternText}\n${REWRITE_HEADER}\n${repeated.join("\n")}`,
						"Copy-ready whole-span interpretation:",
						`${header}\n${operation.patternText}\n${REWRITE_HEADER}\n${rewriteSelectionSpans(content, candidate, repeated)}`,
					].join("\n"),
				);
			}
		}
		let changes = 0;
		for (const located of orderedCandidates) {
			let candidate = located;
			let resolvedCandidateRewrite = baseResolvedRewrite;
			if (loneReference && !operation.all) {
				const referenced = removedByOperation[Number(loneReference[1]) - 1];
				const anchorLineStart = content.lastIndexOf("\n", Math.max(0, candidate.matchStart - 1)) + 1;
				const anchorNewline = content.indexOf("\n", candidate.matchEnd);

View on GitHub (pinned to 9690622007)

Solutions

  1. Pick the intended interpretation from the two copy-ready payloads in the error and resubmit that exact payload.
  2. For per-selection semantics: repeat the rewrite text once per selection in REWRITE.
  3. For whole-span semantics: rewrite the entire matched span as final text (use the payload whose REWRITE was generated by rewriteSelectionSpans).

Example fix

// before (ambiguous)
»
<sel>a</sel> <sel>b</sel>
====
X

// after (per-selection chosen)
»
<sel>a</sel> <sel>b</sel>
====
X
X
Defensive patterns

Strategy: retry

Validate before calling

function disambiguateMultiSelection(rewrite: string, selectionCount: number): string {
  // choose per-selection semantics explicitly: repeat rewrite once per selection
  return Array.from({ length: selectionCount }, () => rewrite).join("\n");
}

Try / catch

try {
  applySloppyEdit(payload);
} catch (err) {
  if (err instanceof Error && err.message.includes("proves neither positional substitution nor whole-span replacement")) {
    const perSelection = err.message.split("Copy-ready per-selection interpretation:\n")[1]
      ?.split("Copy-ready whole-span interpretation:")[0];
    if (perSelection) applySloppyEdit(perSelection); else throw err;
  } else throw err;
}

Prevention

When it happens

Trigger: An operation with multiple selectionRanges where the base resolved REWRITE neither matches repeated per-selection substitution nor passes rewriteProvesWholeSpan against any candidate.

Common situations: Ambiguous multi-selection rewrites where the author meant one of the two semantics; model payloads mixing per-selection text with whole-span text; edits where whitespace differences break the whole-span proof.

Related errors


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