can1357/oh-my-pi · error · Error

Commit summary cannot be empty

Error message

Commit summary cannot be empty

What it means

conventionalCommit() requires a non-empty summary: after type validation, it trims the summary and throws if nothing remains. A conventional commit without a subject line is invalid, so construction is refused rather than emitting an empty commit message.

Source

Thrown at packages/coding-agent/src/commit/conventional/commit-types.ts:155

		scope: coerceOptionalScope(input.scope),
		summary: typeof input.summary === "string" ? input.summary : undefined,
		details: normalizeDetails(input.details),
		issueRefs: stringsFrom(input.issueRefs),
	};
}

/** Build a normalized conventional commit value. */
export function conventionalCommit(input: {
	type: string;
	scope?: unknown;
	summary: string;
	body?: readonly string[];
	footers?: readonly string[];
}): ConventionalCommit {
	const type = canonicalCommitType(input.type);
	if (!type) throw new Error(`Invalid commit type: ${input.type}`);
	const scope = coerceOptionalScope(input.scope);
	if (!input.summary.trim()) throw new Error("Commit summary cannot be empty");
	return {
		type,
		scope,
		summary: input.summary,
		body: [...(input.body ?? [])],
		footers: [...(input.footers ?? [])],
	};
}

function sanitizeScopeSegment(segment: string): string | null {
	const out: string[] = [];
	let lastWasSeparator = false;
	for (const char of segment.trim()) {
		if (/^[a-z0-9]$/.test(char)) {
			out.push(char);
			lastWasSeparator = false;
		} else if (char === "-" || char === "_") {
			if (out.length > 0 && !lastWasSeparator) {

View on GitHub (pinned to 9690622007)

Solutions

  1. Provide a non-empty summary string before constructing the commit
  2. Re-run generation — truncation (stopReason length) often causes missing summaries
  3. If parsing markdown, ensure the summary/heading line is present in the source
  4. Add a fallback summary (e.g. derived from the file changes) when input is optional

Example fix

// before
conventionalCommit({ type: "fix", summary: detail.trim() ?? "" })
// after
const summary = detail.trim() || "update affected modules";
conventionalCommit({ type: "fix", summary });
Defensive patterns

Strategy: validation

Validate before calling

const summary = (input.summary ?? "").trim();
if (!summary) throw new Error("Summary required before building commit");

Type guard

function hasSummary(s: unknown): s is string {
  return typeof s === "string" && s.trim().length > 0;
}

Try / catch

try {
  const commit = conventionalCommit({ ...parsed, summary: parsed.summary });
} catch (err) {
  if (err.message === "Commit summary cannot be empty") {
    // regenerate or derive a summary from the diff before retrying
  } else throw err;
}

Prevention

When it happens

Trigger: Calling conventionalCommit (directly or via generateConventionalCommit/messageFromAnalysis/parseFastCommitMarkdown) with summary "", whitespace, or undefined coerced to an empty string — typically when model output omitted the summary line or a parser produced an empty capture.

Common situations: LLM response truncated before the summary was generated; markdown parse where the heading line is missing; programmatic use passing summary from an optional field without a default.

Related errors


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