affaan-m/ECC · error
Invalid repo format: " ". Expected "owner/repo".
Error message
Invalid repo format: "${repo}". Expected "owner/repo". What it means
normalizeRepo converts a repository reference string into { owner, name } by splitting on '/' and requiring exactly two non-empty segments. Any input that doesn't yield exactly two parts — full URLs, 'owner/name/extra', empty strings, values without a slash, or non-string inputs coerced via String() — is rejected with this error naming the received value.
Solutions
- Pass the canonical 'owner/name' string form
- Strip the URL prefix if you have a full URL: new URL(repo).pathname.replace(/^\//, '') then validate
- Resolve the repo from process.env.GITHUB_REPOSITORY when not explicitly provided
- Pre-validate with a regex like /^[^/]+\/[^/]+$/ before calling
Example fix
// before
listIssues('https://github.com/acme/widgets', ...) // 4 parts -> throws
// after
const repo = process.env.GITHUB_REPOSITORY || 'acme/widgets'; // 'acme/widgets'
listIssues(repo, ...) Defensive patterns
Strategy: validation
Validate before calling
function parseRepo(repo) { const m = /^(?:https:\/\/github\.com\/)?([\w.-]+)\/([\w.-]+)$/.exec(String(repo || '').replace(/\.git$/, '')); if (!m) throw new Error(`bad repo: ${repo}`); return { owner: m[1], name: m[2] }; } Type guard
const isOwnerName = (v) => typeof v === 'string' && /^[^/\s]+\/[^/\s]+$/.test(v.trim());
Try / catch
try { listIssues(repo, opts); } catch (e) { if (String(e.message).includes('Invalid repo format')) console.error(`normalize '${e.message.match(/"(.*)"/)?.[1]}' to owner/name before calling`); throw e; } Prevention
- Always store and pass repos as 'owner/name', never full URLs
- Resolve repo from GITHUB_REPOSITORY as a fallback in CI
- Trim and validate the value at the entry point
- Handle non-string inputs (null/undefined) before they reach normalizeRepo
When it happens
Trigger: Passing 'owner' (no slash), 'https://github.com/owner/name' (four parts), 'owner//name' (still fine after filtering, but 'a/b/c' fails), an empty string, or undefined/null (coerced to '') into normalizeRepo or any gh-api call that takes a repo.
Common situations: Passing a GitHub URL instead of the 'owner/name' shorthand; GITHUB_REPOSITORY missing so an empty string is used; repo names containing slashes for nested services mistakenly assumed supported; concatenating owner and name with the wrong separator.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- invalid discussion id
- invalid issueNumber: expected positive integer, got
- invalid repo: expected non-empty string, got
- Invalid repo
- invalid repository
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/35f3224247d0c747.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/github-coordination/gh-api.js:8
'use strict';
const { spawnSync } = require('child_process');
function normalizeRepo(repo) {
const parts = String(repo || '').split('/').filter(Boolean);
if (parts.length !== 2) {
throw new Error(`Invalid repo format: "${repo}". Expected "owner/repo".`);
}
const [owner, name] = parts;
return { owner, name };
}
function normalizeIssueNumber(value) {
const parsed = Number.parseInt(String(value), 10);
if (!Number.isFinite(parsed) || parsed <= 0) {
throw new Error(`Invalid issue number: ${value}`);
}
return parsed;
}
function normalizeLabelValue(label) {
if (typeof label === 'string') {
return label.trim();
}
if (label && typeof label === 'object') {View on GitHub (pinned to 8321021c54)