can1357/oh-my-pi · error · Error

`PUT ${startLine}.=${endLine}:` rejected: a selected boundar

Error message

`PUT ${startLine}.=${endLine}:` rejected: a selected boundary row is required for the file to parse, but the body indentation does not establish whether it belongs before or after that row. Re-read the region and re-issue with a range that excludes every unchanged boundary row.

What it means

When a hashline PUT edit groups into zero boundary-combination groups, applyEdits cannot determine placement of an unchanged boundary row whose indentation is ambiguous. If such an ambiguous group was recorded, it throws the descriptive ambiguousBoundaryPlacementMessage telling the caller to re-read and re-issue with a range excluding unchanged boundary rows.

Source

Thrown at packages/hashline/src/apply.ts:798

	if (path === undefined) return undefined;

	const groups: { group: ReplacementGroup; variants: GroupVariant[] }[] = [];
	let ambiguousGroup: ReplacementGroup | undefined;
	let i = 0;
	while (i < edits.length) {
		const group = findReplacementGroup(edits, i);
		if (group) {
			const built = buildGroupVariants(group, edits, fileLines, path, baselineParses);
			if (built.ambiguous && ambiguousGroup === undefined) ambiguousGroup = group;
			if (built.variants.length > 0) groups.push({ group, variants: built.variants });
			i = group.deleteIndices[group.deleteIndices.length - 1] + 1;
		} else {
			i++;
		}
	}
	if (groups.length === 0) {
		if (ambiguousGroup) {
			throw new Error(ambiguousBoundaryPlacementMessage(ambiguousGroup.startLine, ambiguousGroup.endLine));
		}
		return undefined;
	}

	let combos: BoundaryCombo[] = [{ variants: [], touched: 0, kept: 0, dropped: 0 }];
	for (const { variants } of groups) {
		const next: BoundaryCombo[] = [];
		for (const combo of combos) {
			next.push({ ...combo, variants: [...combo.variants, null] });
			for (const variant of variants) {
				next.push({
					variants: [...combo.variants, variant],
					touched: combo.touched + 1,
					kept: combo.kept + variant.kept,
					dropped: combo.dropped + variant.dropped,
				});
			}
		}

View on GitHub (pinned to 9690622007)

Solutions

  1. Re-read the region and re-issue the PUT with a range that excludes every unchanged boundary row
  2. Narrow the edit to only the lines that actually change
  3. If the boundary row must change, include new content that makes its placement unambiguous
  4. Use a different edit form (single-line PUT or full rewrite) when block boundaries are ambiguous

Example fix

// before
`PUT 10.=20:` // includes unchanged boundary row 10, ambiguous indentation
// after — re-read region, then exclude unchanged boundary line
`PUT 11.=20:` // start after the unchanged boundary row
Defensive patterns

Strategy: try-catch

Try / catch

try {
  applyHashlinePut(start, end, body);
} catch (e) {
  if (e.message.includes("boundary row is required")) {
    // re-read region, re-issue with range excluding unchanged boundary rows
  }
}

Prevention

When it happens

Trigger: Issuing a `PUT start.=end:` edit where the selected range includes a boundary row (first/last of a block) that is unchanged, and the body's indentation does not disambiguate whether that row belongs before or after the edited region — so no valid combination of boundary rows can be built.

Common situations: Model selecting an overly broad line range that spans an unchanged blank/indentation-only boundary row; editing a block whose first or last line shares indentation with surrounding code; stale line ranges after the file changed.

Related errors


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