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
- Provide a non-empty summary string before constructing the commit
- Re-run generation — truncation (stopReason length) often causes missing summaries
- If parsing markdown, ensure the summary/heading line is present in the source
- 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
- Check model stopReason — truncated responses often lack the summary
- Default missing summaries from diff content instead of passing empty strings
- Trim and validate summaries at the parse boundary
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
- Invalid commit type: ${input.type}
- Unsupported language '{value}'. Supported: {}
- Unable to infer language from file extension: {}. Specify `l
- Invalid pattern: {err}
- Failed to load tree-sitter language: {err}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/7cca7bc79b5660a2.
Report an issue: GitHub.