can1357/oh-my-pi · error

No hashline sections found in input.

Error message

No hashline sections found in input.

What it means

executeHashlineSingle() parses the raw tool input with Patch.parse and throws when no hashline sections were found. The edit tool requires at least one `@@@ path:tag ...` section; input that is empty, plain diff text without hashline headers, or malformed yields zero sections and the tool aborts before touching any file.

Source

Thrown at packages/coding-agent/src/edit/hashline/execute.ts:208

		move: result.moveDest,
		sourcePath: result.moveDest ? sourcePath : undefined,
		oldText: result.before,
		newText: result.after,
		beforePreview: result.blockResolutions?.map(formatBlockResolution),
		warnings: result.warnings,
	});
	return {
		toolResult: toEditToolResult(editResult),
		perFileResult: editResult.perFileResult,
	};
}

export async function executeHashlineSingle(
	options: ExecuteHashlineSingleOptions,
): Promise<AgentToolResult<EditToolDetails, typeof hashlineEditParamsSchema>> {
	const patch = Patch.parse(options.input, { cwd: options.session.cwd });
	if (patch.sections.length === 0) {
		throw new Error("No hashline sections found in input.");
	}

	const fs = new HashlineFilesystem({
		session: options.session,
		writethrough: options.writethrough,
		beginDeferredDiagnosticsForPath: options.beginDeferredDiagnosticsForPath,
		signal: options.signal,
		batchRequest: options.batchRequest,
	});
	const snapshots = getFileSnapshotStore(options.session);
	const enforceSeenLines = options.session.settings.get("edit.enforceSeenLines");
	const patcher = new Patcher({ fs, snapshots, blockResolver: nativeBlockResolver, enforceSeenLines });

	// Named registers persist across edit calls; the anonymous register is
	// batch-local. Each batch starts without anonymous state and publishes
	// named registers only after writes land.
	const sessionClipboard = getEditClipboard(options.session);
	const clipboard = startClipboardBatch(sessionClipboard);

View on GitHub (pinned to 9690622007)

Solutions

  1. Re-author the input with at least one valid `@@@ <path>:<tag>` header followed by hashline ops.
  2. Copy the header format directly from a read/search result rather than reconstructing it.
  3. If a unified diff was intended, use the patch tool instead of the hashline edit tool.

Example fix

// before
--- a/src/a.ts
+++ b/src/a.ts
@@ -1 +1 @@
-old
+new
// after
@@@ src/a.ts:7c4d
- old
+ new
Defensive patterns

Strategy: validation

Validate before calling

if (!/^@@@ \S+:[0-9a-f]{4}/m.test(input)) {
  throw new Error('Edit input contains no hashline sections; add an `@@@ path:tag` header');
}
await executeHashlineSingle({ ...options, input });

Type guard

function isHashlinePatch(input: string): boolean {
  return input.split('\n').some((l) => /^@@@ \S+/.test(l.trim()));
}

Try / catch

try {
  return await executeHashlineSingle(options);
} catch (e) {
  if (e instanceof Error && e.message === 'No hashline sections found in input.') {
    return convertUnifiedDiffToHashlineAndRetry(options.input);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling the hashline edit tool with empty input, with a unified-diff that lacks `@@@ file` headers, with headers in a format Patch.parse does not recognize, or with only comments/whitespace.

Common situations: A model emitting standard git/unified diffs instead of hashline sections; truncation dropping the header line; wrong tool chosen (bash-applying a patch instead of using the edit tool).

Related errors


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