can1357/oh-my-pi · error · Error

${REWRITE_HEADER}${reference[1]} must reference an earlier d

Error message

${REWRITE_HEADER}${reference[1]} must reference an earlier deletion operation.

What it means

resolveRewriteReferences lets a REWRITE line of the form »N pull in the text deleted by an earlier operation N. When the referenced operation index does not exist among the operations processed so far (removedByOperation has no entry at index N-1), the library throws this error. It prevents dangling back-references to non-existent or later deletions.

Source

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

		if (normalized.text.slice(matchEnd, matchEnd + overlap) !== rewriteNormalized.slice(-overlap)) continue;
		let end = normalized.ends[matchEnd + overlap - 1] ?? candidate.end;
		const newline = content.indexOf("\n", end);
		const lineEnd = newline === -1 ? content.length : newline;
		if (/^[ \t]*$/u.test(content.slice(end, lineEnd))) end = lineEnd;
		return { start: candidate.start, end };
	}
	return undefined;
}

function resolveRewriteReferences(rewrite: string, removedByOperation: Array<string | undefined>): string {
	return rewrite
		.split("\n")
		.map(line => {
			const reference = line.trim().match(/^»([1-9]\d*)$/u);
			if (!reference) return line;
			const referenced = removedByOperation[Number(reference[1]) - 1];
			if (referenced === undefined) {
				throw new Error(`${REWRITE_HEADER}${reference[1]} must reference an earlier deletion operation.`);
			}
			return referenced;
		})
		.join("\n");
}

/**
 * Locate an operation's candidates; when the authored pattern finds nothing,
 * retry echo-recovery variants (`X⟪X⟫` dedup, echoed anchor lines) and keep
 * the original error when every variant fails too.
 */
/**
 * Delimiter-garbled punctuation selections (`i[----]{+++}+` for `++`→`--`):
 * the marker glyphs absorb the payload's own `-`/`+` characters, scrambling
 * which side is current. Enumerate run-length/side variants for punct-only
 * selections; the file disambiguates — exactly one variant's old side exists.
 */
function punctuationPairVariants(operation: Operation): Operation[] {

View on GitHub (pinned to 9690622007)

Solutions

  1. Change the »N reference to point at an operation defined earlier that actually deletes text.
  2. Remove the »N line if the referenced deletion no longer exists; type the content literally instead.
  3. Recount operations in the payload so reference numbers match the 1-based deletion order.

Example fix

// before
» 3   // only 2 earlier deletions exist

// after
» 2
Defensive patterns

Strategy: validation

Validate before calling

function assertReferencesValid(payload: string, deletionCount: number) {
  for (const m of payload.matchAll(/^»([1-9]\d*)$/gmu)) {
    const n = Number(m[1]);
    if (n > deletionCount) throw new Error(`Reference »${n} has no earlier deletion operation`);
  }
}

Type guard

const isValidDeletionReference = (n: number, removedByOperation: unknown[]): boolean =>
  Number.isInteger(n) && n >= 1 && removedByOperation[n - 1] !== undefined;

Try / catch

try {
  applySloppyEdit(payload);
} catch (err) {
  if (err instanceof Error && /»\d+.*earlier deletion/.test(err.message)) {
    payload = inlineDanglingReferences(payload);
    applySloppyEdit(payload);
  } else throw err;
}

Prevention

When it happens

Trigger: A REWRITE line matching /^»([1-9]\d*)$/ refers to an operation number greater than the number of earlier deletion operations, or that operation made no deletion (nothing recorded in removedByOperation).

Common situations: Author miscounts operation numbers (they are 1-based and only deletions register); payload reorderings after adding/removing an earlier edit; model-generated cross-operation references pointing past the end.

Related errors


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