can1357/oh-my-pi · error · ToolError
fill is mutually exclusive with title and body
Error message
fill is mutually exclusive with title and body
What it means
`fill` is an alternative to explicit title/body, not a combination: fill derives title and body from commit messages, and supplying any of title or body alongside it is ambiguous. The tool rejects the call up front rather than letting gh fail or silently preferring one source.
Source
Thrown at packages/coding-agent/src/tools/gh-pr-checkout.ts:591
params: GithubInput,
signal: AbortSignal | undefined,
): Promise<AgentToolResult<GhToolDetails>> {
const repo = normalizeOptionalString(params.repo);
const title = normalizeOptionalString(params.title);
const body = params.body;
const base = normalizeOptionalString(params.base);
const head = normalizeOptionalString(params.head);
const draft = params.draft ?? false;
const fill = params.fill ?? false;
const reviewers = normalizePrIdentifierList(params.reviewer);
const assignees = normalizePrIdentifierList(params.assignee);
const labels = normalizePrIdentifierList(params.label);
if (!fill && !title) {
throw new ToolError("title is required unless fill is true");
}
if (fill && (title || body !== undefined)) {
throw new ToolError("fill is mutually exclusive with title and body");
}
const args = ["pr", "create"];
appendRepoFlag(args, repo);
if (title) args.push("--title", title);
if (base) args.push("--base", base);
if (head) args.push("--head", head);
if (draft) args.push("--draft");
if (fill) args.push("--fill");
for (const reviewer of reviewers) args.push("--reviewer", reviewer);
for (const assignee of assignees) args.push("--assignee", assignee);
for (const label of labels) args.push("--label", label);
let bodyDir: string | undefined;
try {
if (!fill) {
if (body !== undefined && body.length > 0) {
// Route through a temp file so multi-KB bodies stay clear of anyView on GitHub (pinned to 9690622007)
Solutions
- Remove the title/body parameters and rely solely on fill=true to generate them from commits.
- Or remove fill (leave it false) and supply your explicit title/body.
- If a framework injects a default empty body, set it to undefined (not "") so fill can be used.
Example fix
// before op pr_create --fill --title "Fix login redirect" // after (choose one) op pr_create --fill op pr_create --title "Fix login redirect" --body "Fixes #42"
Defensive patterns
Strategy: validation
Validate before calling
if (params.fill && (params.title || params.body !== undefined)) {
throw new Error("remove title/body when using fill=true");
} Type guard
function fillExclusive(p: { fill?: boolean; title?: string; body?: string }): boolean {
return !(p.fill && (p.title !== undefined || p.body !== undefined));
} Try / catch
try {
await op.prCreate(params);
} catch (err) {
if (err instanceof ToolError && err.message.includes("mutually exclusive")) {
const { fill, title, body, ...rest } = params;
await op.prCreate(fill ? rest : { ...rest, title, body }); // pick one mode
} else throw err;
} Prevention
- Choose one mode per call: explicit title/body OR fill — never both.
- Strip default-injected empty body fields (use undefined, not "") when fill is desired.
- Keep pr_create wrappers with a single options shape to avoid flag collisions.
- Review call sites that merge user params with fill defaults.
When it happens
Trigger: Calling pr_create with fill=true together with a non-empty title, or fill=true together with a body parameter (body present, even empty string, counts as `body !== undefined`).
Common situations: Template/default params that always include a body field, merged with a fill flag from a different code path; users thinking fill only affects the body while supplying a custom title.
Related errors
- title is required unless fill is true
- 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/d137ba6750de2693.
Report an issue: GitHub.