{"record":{"id":"985d92153bbabb43","repo":"affaan-m/ECC","slug":"invalid-repo-expected-non-empty-string-got-jso","errorCode":null,"errorMessage":"invalid repo: expected non-empty string, got ${JSON.stringify(repo)}","messagePattern":"invalid repo: expected non-empty string, got (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/lib/github-coordination/actions.js","lineNumber":21,"sourceCode":"const { loadPolicy } = require('./policy');\nconst { mergeIssueBody, normalizeBodyForComparison } = require('./parsing');\nconst { getIssue, listIssues, editIssue, commentIssue, normalizeLabels } = require('./gh-api');\nconst {\n  assertIssueClaimable,\n  buildIssueComment,\n  buildIssueStateFromAction,\n  desiredLabelsForState,\n  getCoordinationState,\n  summarizeStateForOutput,\n  syncIssueLabels,\n  verifyDependenciesClosed,\n} = require('./state');\nconst { upsertCoordinationWorkItem } = require('./store');\nconst { extractIssueReferences, extractTasks } = require('./parsing');\n\nfunction assertValidRepo(repo) {\n  if (typeof repo !== 'string' || !repo.trim()) {\n    throw new Error(`invalid repo: expected non-empty string, got ${JSON.stringify(repo)}`);\n  }\n}\n\nfunction assertValidIssueNumber(issueNumber) {\n  if (!Number.isFinite(issueNumber) || issueNumber <= 0 || !Number.isInteger(issueNumber)) {\n    throw new Error(`invalid issueNumber: expected positive integer, got ${JSON.stringify(issueNumber)}`);\n  }\n}\n\nfunction staleCoordinationLabels(issue, nextLabels, policy) {\n  const epicLabel = policy.labels && policy.labels.epic;\n  return normalizeLabels(issue.labels).filter(l =>\n    (l.startsWith('coordination:') || l === epicLabel) && !nextLabels.includes(l)\n  );\n}\n\n// applyClaim performs a read (getIssue) → check (assertIssueClaimable) → write\n// (editIssue) sequence that is NOT atomic. Two concurrent callers can both read","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/github-coordination/actions.js#L3-L39","documentation":"assertValidRepo is the entry-point guard used by every apply* action (claim, sync, validate, publish, review, decompose) in the github-coordination library. It requires the repo argument to be a non-empty, non-whitespace string identifying the GitHub repository. Failing that, it throws with a JSON dump of the received value so the caller can see what was actually passed.","triggerScenarios":"Calling applyClaim/applySync/applyValidate/applyPublish/applyReview/applyDecompose with repo = undefined/null (missing config field), an empty or whitespace-only string, or a non-string value such as a number or object.","commonSituations":"Missing GITHUB_REPOSITORY env var in CI so the repo option resolves to undefined; a config file where the repo key is empty or commented out; passing a parsed object like {owner, repo} instead of the 'owner/name' string; shell interpolation expanding to an empty value.","solutions":["Pass a repo string like 'owner/name' (or resolve it from process.env.GITHUB_REPOSITORY) to the apply* function","Fix the config file or CLI flag so the repo value is actually populated","Validate/normalize the repo (e.g. via normalizeRepo) before calling the action","Check that CI provides GITHUB_REPOSITORY and that your script reads it correctly"],"exampleFix":"// before\napplyPublish(options.repo, 42, {}) // options.repo undefined\n// after\nconst repo = options.repo || process.env.GITHUB_REPOSITORY;\nif (typeof repo !== 'string' || !repo.trim()) throw new Error('repo not configured');\napplyPublish(repo, 42, {})","handlingStrategy":"type-guard","validationCode":"function assertRepo(repo) { if (typeof repo !== 'string' || !repo.trim()) throw new Error(`repo not configured: ${JSON.stringify(repo)}`); }\nassertRepo(repo);","typeGuard":"const isValidRepoArg = (repo) => typeof repo === 'string' && repo.trim().length > 0;","tryCatchPattern":"try { applyClaim(repo, n, opts); } catch (e) { if (String(e.message).startsWith('invalid repo')) console.error('resolve repo from config or GITHUB_REPOSITORY before calling'); throw e; }","preventionTips":["Default to process.env.GITHUB_REPOSITORY when the repo option is absent","Validate repo at the CLI/config entry point once, before any apply* call","Avoid passing parsed objects where the 'owner/name' string is expected","Fail fast at startup if the repo configuration is missing"],"tags":["validation","github","argument"],"backgroundTag":"missing-required-argument","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}