can1357/oh-my-pi · error · ToolError

ref_diff preflight requires base_revision and head_revision

Error message

ref_diff preflight requires base_revision and head_revision

What it means

For target_kind='ref_diff', the scan compares two git revisions, so both base_revision and head_revision are required. If either is missing/empty, targetFromParams throws this preflight ToolError before any scanning starts.

Source

Thrown at packages/coding-agent/src/tools/security-scan.ts:72

	cloudStats?: CodexSecurityCloudStats;
	cloudScan?: { id: string; repositoryUrl: string };
	importedScan?: { id: string; findingCount: number };
}

function targetFromParams(params: SecurityScanParams): SecurityTargetRequest {
	const common = { includePaths: params.include_paths, excludePaths: params.exclude_paths };
	switch (params.target_kind ?? "repository") {
		case "scoped_path": {
			if (!params.include_paths?.some(value => value.trim().length > 0)) {
				throw new ToolError("scoped_path security scans require at least one include path");
			}
			return { kind: "scoped_path", includePaths: params.include_paths, excludePaths: params.exclude_paths };
		}
		case "working_tree":
			return { kind: "working_tree", ...common };
		case "ref_diff":
			if (!params.base_revision || !params.head_revision) {
				throw new ToolError("ref_diff preflight requires base_revision and head_revision");
			}
			return {
				kind: "ref_diff",
				baseRevision: params.base_revision,
				headRevision: params.head_revision,
				...common,
			};
		default:
			return { kind: "repository", ...common };
	}
}

function requireValue(value: string | undefined, label: string): string {
	if (!value?.trim()) throw new ToolError(`${label} is required for this action`);
	return value.trim();
}

function cloudClientForSession(session: ToolSession, credentialId?: number): CodexSecurityCloudClient {

View on GitHub (pinned to 9690622007)

Solutions

  1. Supply both base_revision and head_revision (branch names, tags, or SHAs), e.g. { target_kind: "ref_diff", base_revision: "main", head_revision: "HEAD" }
  2. If you actually want the current state scanned, use target_kind='working_tree' or 'repository' instead
  3. Validate both revision strings are non-empty before invoking

Example fix

// before
scan({ target_kind: "ref_diff", head_revision: "HEAD" });
// after
scan({ target_kind: "ref_diff", base_revision: "main", head_revision: "HEAD" });
Defensive patterns

Strategy: validation

Validate before calling

if (params.target_kind === "ref_diff" && (!params.base_revision?.trim() || !params.head_revision?.trim())) throw new Error("ref_diff needs both base_revision and head_revision");

Try / catch

try { await securityScan(params); } catch (e) { if (e instanceof ToolError && e.message.includes("ref_diff preflight")) { return securityScan({ ...params, base_revision: params.base_revision || "main", head_revision: params.head_revision || "HEAD" }); } throw e; }

Prevention

When it happens

Trigger: Calling security-scan with target_kind='ref_diff' and omitting base_revision, head_revision, or both; passing empty strings for either.

Common situations: Model forgets the revision pair when it wants to scan a diff; caller has only one of the two refs (e.g. HEAD but no base branch name); empty-string values from unset variables.

Understand the failure class

Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.

Related errors


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