{"record":{"id":"6c70fe625a2d44cb","repo":"affaan-m/ECC","slug":"issue-issuenumber-cannot-be-published-review","errorCode":null,"errorMessage":"Issue #${issueNumber} cannot be published: review approval required (current: ${state.review})","messagePattern":"Issue #(.+?) cannot be published: review approval required \\(current: (.+?)\\)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/lib/github-coordination/actions.js","lineNumber":189,"sourceCode":"    validations,\n    missingDependencies,\n  };\n}\n\nfunction applyPublish(repo, issueNumber, options = {}, context = {}) {\n  assertValidRepo(repo);\n  assertValidIssueNumber(issueNumber);\n  const policy = context.policy || loadPolicy(context.rootDir || process.cwd(), options.configPath);\n  const issue = getIssue(repo, issueNumber, options);\n  const state = getCoordinationState(issue, policy);\n  const validation = applyValidate(repo, issueNumber, { ...options, dryRun: true }, context, issue);\n\n  if (!validation.ok) {\n    throw new Error(`Issue #${issueNumber} is not ready to publish: ${validation.validations.map(entry => `${entry.check}=${entry.ok}`).join(', ')}`);\n  }\n\n  if (policy.review && policy.review.required && state.review !== 'approved') {\n    throw new Error(`Issue #${issueNumber} cannot be published: review approval required (current: ${state.review})`);\n  }\n\n  const nextState = buildIssueStateFromAction(issue, state, 'publish', {\n    status: 'published',\n    validation: 'passed',\n    review: state.review === 'changes-requested' ? state.review : 'approved',\n    projectState: 'done',\n  }, policy);\n  const trackedIssue = {\n    ...issue,\n    labels: desiredLabelsForState(nextState, policy),\n  };\n\n  if (!options.dryRun) {\n    const body = mergeIssueBody(issue, nextState, policy);\n    editIssue(repo, issueNumber, {\n      body,\n      addLabels: trackedIssue.labels,","sourceCodeStart":171,"sourceCodeEnd":207,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/scripts/lib/github-coordination/actions.js#L171-L207","documentation":"Thrown by applyPublish after all structural validations pass but the policy requires review approval (policy.review.required) and the issue's current review state is not 'approved' (e.g. 'pending', 'changes-requested', 'none'). This enforces a human gate before publication so unreviewed work cannot be published even if structurally valid.","triggerScenarios":"policy.review.required is true and the issue has no approval; review is in 'changes-requested' state; review was requested but never granted; the review label/state was not synced from GitHub.","commonSituations":"Team policy mandates approval but the PR/issue skipped review; a reviewer requested changes that were not addressed; review state is tracked via labels and the label is missing/stale.","solutions":["Obtain review approval on the issue/PR and sync its state (e.g. add the approval label or set review state) before publishing.","If changes were requested, address them and get re-approval to move the state from 'changes-requested' to 'approved'.","Confirm the policy.review.required setting — if review is genuinely optional for this flow, set required:false in the policy config.","Verify the review-state source (labels vs gh API) is correctly populated; a stale/missing label can make an approved issue look unapproved."],"exampleFix":"// before\napplyPublish(repo, issueNumber);\n\n// after — check review state first and guide the user\nconst state = getCoordinationState(getIssue(repo, issueNumber), policy);\nif (policy.review?.required && state.review !== 'approved') {\n  throw new Error(`Cannot publish: review is '${state.review}'. Get approval, then retry.`);\n}\napplyPublish(repo, issueNumber);","handlingStrategy":"validation","validationCode":"const state = getCoordinationState(getIssue(repo, issueNumber), policy);\nif (policy.review && policy.review.required && state.review !== 'approved') {\n  throw new Error(`Review approval required (current: ${state.review}).`);\n}","typeGuard":"function isReviewApproved(state, policy) {\n  return !(policy && policy.review && policy.review.required) || state.review === 'approved';\n}","tryCatchPattern":"try {\n  applyPublish(repo, issueNumber);\n} catch (e) {\n  if (/review approval required/.test(e.message)) { requestReview(issueNumber); return; }\n  throw e;\n}","preventionTips":["Get review approval and sync its state before publishing.","Address changes-requested feedback and obtain re-approval.","If review is optional for a flow, set policy.review.required=false explicitly."],"tags":["github-coordination","publish","review","policy","governance"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}