paperclipai/paperclip · error · Error
Selector '${selector}' is ambiguous (matches both an ID and
Error message
Selector '${selector}' is ambiguous (matches both an ID and a shortname). Re-run with --by id or --by prefix. What it means
Thrown by resolveCompanyForDeletion in auto mode when the selector matches both a company id and a different company's issue prefix. Without --by, the resolver cannot decide which company to target, so it refuses and asks the caller to disambiguate.
Source
Thrown at cli/src/commands/client/company.ts:1300
const idMatch = companies.find((company) => company.id === selector);
const prefixMatch = companies.find((company) => matchesPrefix(company, selector));
if (by === "id") {
if (!idMatch) {
throw new Error(`No company found by ID '${selector}'.`);
}
return idMatch;
}
if (by === "prefix") {
if (!prefixMatch) {
throw new Error(`No company found by shortname/prefix '${selector}'.`);
}
return prefixMatch;
}
if (idMatch && prefixMatch && idMatch.id !== prefixMatch.id) {
throw new Error(
`Selector '${selector}' is ambiguous (matches both an ID and a shortname). Re-run with --by id or --by prefix.`,
);
}
if (idMatch) return idMatch;
if (prefixMatch) return prefixMatch;
throw new Error(
`No company found for selector '${selector}'. Use company ID or issue prefix (for example PAP).`,
);
}
export function assertDeleteConfirmation(company: Company, opts: CompanyDeleteOptions): void {
if (!opts.yes) {
throw new Error("Deletion requires --yes.");
}
const confirm = opts.confirm?.trim();View on GitHub (pinned to 67001ec6eb)
Solutions
- Re-run with '--by id' to target the company whose id matches.
- Re-run with '--by prefix' to target the company whose issue prefix matches.
- Use a longer/unique selector (full company id) to avoid the collision entirely.
- If collisions are frequent, consider renaming a prefix to avoid overlap.
Example fix
# before paperclipai company delete PAP --yes --confirm PAP # ambiguous # after paperclipai company delete PAP --by prefix --yes --confirm PAP
Defensive patterns
Strategy: validation
Validate before calling
function detectAmbiguousSelector(companies: { id: string; issuePrefix: string }[], selector: string): void {
const idMatch = companies.find((c) => c.id === selector);
const prefixMatch = companies.find((c) => c.issuePrefix.toUpperCase() === selector.toUpperCase());
if (idMatch && prefixMatch && idMatch.id !== prefixMatch.id) {
throw new Error(`Selector '${selector}' is ambiguous. Specify --by id or --by prefix.`);
}
} Type guard
function selectorIsUnambiguous(companies: { id: string; issuePrefix: string }[], selector: string): boolean {
const idMatch = companies.find((c) => c.id === selector);
const prefixMatch = companies.find((c) => c.issuePrefix.toUpperCase() === selector.toUpperCase());
return !(idMatch && prefixMatch && idMatch.id !== prefixMatch.id);
} Prevention
- Default to '--by id' with full ids to sidestep collisions entirely.
- Rename prefixes that collide with any company id.
- Warn operators when prefix and id namespaces overlap.
When it happens
Trigger: A selector like 'PAP' that is simultaneously a company's issue prefix and another company's id (e.g. an id that happens to read 'PAP'). Auto mode with by='auto' (default) and both lookups hit different rows.
Common situations: Short ids or prefixes that collide across the company set. Renamed prefixes that now match an existing id. Multi-tenant setups where prefixes and ids overlap by coincidence.
Related errors
- No company found by ID '${selector}'.
- No company found by shortname/prefix '${selector}'.
- No company found for selector '${selector}'. Use company ID
- Company selector is required.
- Deletion requires --yes.
AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12).
Data as JSON: /api/errors/aa0a95dae133e4e5.
Report an issue: GitHub.