{"record":{"id":"f244c3aab02eae7b","repo":"affaan-m/ECC","slug":"unknown-hook-consent-decision-hookconsent","errorCode":null,"errorMessage":"Unknown hook consent decision: ${hookConsent}","messagePattern":"Unknown hook consent decision: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/lib/install/hook-consent.js","lineNumber":165,"sourceCode":"        }\n        : plan.statePreview.resolution,\n    }\n    : plan.statePreview;\n\n  return {\n    ...plan,\n    operations,\n    statePreview: setStatePreviewHookConsent(statePreview, 'declined'),\n    selectedModuleIds: withoutHookRuntimeId(plan.selectedModuleIds),\n    excludedModuleIds: hadHookRuntimeModule && Array.isArray(plan.excludedModuleIds)\n      ? [...new Set([...plan.excludedModuleIds, HOOK_RUNTIME_MODULE_ID])]\n      : plan.excludedModuleIds,\n  };\n}\n\nfunction withHookConsent(plan, hookConsent = null) {\n  if (hookConsent !== null && !HOOK_CONSENT_DECISIONS.includes(hookConsent)) {\n    throw new Error(`Unknown hook consent decision: ${hookConsent}`);\n  }\n  if (hookConsent === 'declined') {\n    return { ...stripHookRuntimeFromPlan(plan), hookConsent };\n  }\n  return {\n    ...plan,\n    hookConsent,\n    statePreview: setStatePreviewHookConsent(plan.statePreview, hookConsent),\n  };\n}\n\nfunction assertHookConsentReady(plan = {}) {\n  if (!planMaterializesHookRuntime(plan)) {\n    return;\n  }\n  if (plan.hookConsent === 'enabled') {\n    return;\n  }","sourceCodeStart":147,"sourceCodeEnd":183,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/install/hook-consent.js#L147-L183","documentation":"withHookConsent() attaches a hook consent decision to an install plan. The decision must be one of the values in HOOK_CONSENT_DECISIONS (e.g. 'enabled', 'declined'); any other non-null string is rejected with this error. It protects the plan from carrying an unrecognized consent state.","triggerScenarios":"Calling withHookConsent(plan, decision) programmatically with a misspelled decision like 'enable', 'Declined', 'yes', or a value from an older API version; reading the consent value from unparsed CLI input without normalizing it.","commonSituations":"Custom automation scripts building install plans; renaming/typoing the decision constant in downstream tooling; upgrading code across a version where the allowed decision values changed.","solutions":["Use an exact allowed decision string — check HOOK_CONSENT_DECISIONS in hook-consent.js and pass 'enabled' or 'declined' verbatim (lowercase).","Normalize user/script input (toLowerCase, trim) before passing it to withHookConsent.","Pass no argument (default null) when there is no consent decision yet and let assertHookConsentReady handle gating later.","If upgrading, update your integration to the current decision vocabulary in the latest ECC version."],"exampleFix":"// before\nwithHookConsent(plan, 'Enable')\n// after\nwithHookConsent(plan, 'enabled')","handlingStrategy":"type-guard","validationCode":"const DECISIONS = ['enabled', 'declined'];\nif (decision !== null && !DECISIONS.includes(decision)) {\n  throw new Error(`Consent decision must be one of ${DECISIONS.join('|')} or null`);\n}","typeGuard":"function isHookConsentDecision(v) {\n  return v === null || v === 'enabled' || v === 'declined';\n}","tryCatchPattern":"try {\n  const plan2 = withHookConsent(plan, decision);\n} catch (err) {\n  if (err.message.startsWith('Unknown hook consent decision')) {\n    console.error(`Bad decision '${decision}'; use 'enabled' or 'declined'`);\n    process.exitCode = 1;\n  } else throw err;\n}","preventionTips":["Import/reuse the module's HOOK_CONSENT_DECISIONS constant instead of hardcoding strings.","Normalize CLI input with trim() and toLowerCase() before mapping to a decision.","Keep decisions centralized in one config module for your tooling.","Add a unit test asserting your wrapper only passes valid decision values."],"tags":["hooks","invalid-enum-value","installer"],"backgroundTag":"invalid-enum-value","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"}