affaan-m/ECC · error · Error
invalid repo: expected non-empty string, got ${JSON.stringif
Error message
invalid repo: expected non-empty string, got ${JSON.stringify(repo)} What it means
Thrown by assertValidRepo in github-coordination/actions.js when repo is not a non-empty string. Every coordination action (applyClaim, applyPublish, etc.) targets exactly one GitHub repository identified as 'owner/name'; a missing repo makes all downstream gh calls meaningless. This guard runs before any network/spawn so it fails fast.
Source
Thrown at scripts/lib/github-coordination/actions.js:21
const { loadPolicy } = require('./policy');
const { mergeIssueBody, normalizeBodyForComparison } = require('./parsing');
const { getIssue, listIssues, editIssue, commentIssue, normalizeLabels } = require('./gh-api');
const {
assertIssueClaimable,
buildIssueComment,
buildIssueStateFromAction,
desiredLabelsForState,
getCoordinationState,
summarizeStateForOutput,
syncIssueLabels,
verifyDependenciesClosed,
} = require('./state');
const { upsertCoordinationWorkItem } = require('./store');
const { extractIssueReferences, extractTasks } = require('./parsing');
function assertValidRepo(repo) {
if (typeof repo !== 'string' || !repo.trim()) {
throw new Error(`invalid repo: expected non-empty string, got ${JSON.stringify(repo)}`);
}
}
function assertValidIssueNumber(issueNumber) {
if (!Number.isFinite(issueNumber) || issueNumber <= 0 || !Number.isInteger(issueNumber)) {
throw new Error(`invalid issueNumber: expected positive integer, got ${JSON.stringify(issueNumber)}`);
}
}
function staleCoordinationLabels(issue, nextLabels, policy) {
const epicLabel = policy.labels && policy.labels.epic;
return normalizeLabels(issue.labels).filter(l =>
(l.startsWith('coordination:') || l === epicLabel) && !nextLabels.includes(l)
);
}
// applyClaim performs a read (getIssue) → check (assertIssueClaimable) → write
// (editIssue) sequence that is NOT atomic. Two concurrent callers can both readView on GitHub (pinned to 01e15490f0)
Solutions
- Pass repo as a non-empty 'owner/name' string.
- Resolve repo from env/config once at startup and fail loudly there if missing: const repo = process.env.GITHUB_REPOSITORY; if (!repo) throw new Error('Set GITHUB_REPOSITORY=owner/name').
- Add a CLI --repo required flag with a validator.
- Unit-test assertValidRepo with undefined/''/number to lock the guard.
Example fix
// before
applyPublish(repo, issueNumber);
// after — resolve and validate at the boundary
const repo = process.env.GITHUB_REPOSITORY;
if (typeof repo !== 'string' || !repo.trim()) {
throw new Error('GITHUB_REPOSITORY must be set to owner/name');
}
applyPublish(repo.trim(), issueNumber); Defensive patterns
Strategy: validation
Validate before calling
if (typeof repo !== 'string' || !repo.trim()) {
throw new Error('repo must be a non-empty "owner/name" string');
} Type guard
function isNonEmptyRepoString(repo) {
return typeof repo === 'string' && repo.trim().length > 0;
} Try / catch
try {
applyPublish(repo, issueNumber);
} catch (e) {
if (/invalid repo/.test(e.message)) { console.error('Set GITHUB_REPOSITORY=owner/name'); process.exit(2); }
throw e;
} Prevention
- Resolve repo from env/config once at startup and fail there if missing.
- Require a --repo CLI flag with validation.
- Unit-test assertValidRepo with undefined/''/number/null.
When it happens
Trigger: Calling applyPublish(undefined, 12) or applyPublish('', 12); repo read from an unset env var or a missing config field; repo passed as an object or number by mistake.
Common situations: Env var ECC_REPO / GITHUB_REPOSITORY unset in CI; config file missing the repo key; CLI flag --repo forgotten; programmatic caller destructured wrong field name.
Related errors
- invalid issueNumber: expected positive integer, got ${JSON.s
- --config-dir must be an existing absolute directory.
- invalid qualification configuration
- --config-dir must exist and contain a regular sixtytwo.yaml
- claim requires an owner.
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/985d92153bbabb43.
Report an issue: GitHub.