Merge pull request #1584 from code-yeongyu/fix/441-matcher-hooks-undefined

fix(hooks): add defensive null check for matcher.hooks to prevent Windows crash (#441)
This commit is contained in:
YeonGyu-Kim
2026-02-07 20:01:28 +09:00
committed by GitHub
6 changed files with 25 additions and 20 deletions

View File

@@ -20,7 +20,7 @@ interface RawClaudeHooksConfig {
function normalizeHookMatcher(raw: RawHookMatcher): HookMatcher {
return {
matcher: raw.matcher ?? raw.pattern ?? "*",
hooks: raw.hooks,
hooks: Array.isArray(raw.hooks) ? raw.hooks : [],
}
}

View File

@@ -91,11 +91,12 @@ export async function executePostToolUseHooks(
const startTime = Date.now()
for (const matcher of matchers) {
for (const hook of matcher.hooks) {
if (hook.type !== "command") continue
for (const matcher of matchers) {
if (!matcher.hooks || matcher.hooks.length === 0) continue
for (const hook of matcher.hooks) {
if (hook.type !== "command") continue
if (isHookCommandDisabled("PostToolUse", hook.command, extendedConfig ?? null)) {
if (isHookCommandDisabled("PostToolUse", hook.command, extendedConfig ?? null)) {
log("PostToolUse hook command skipped (disabled by config)", { command: hook.command, toolName: ctx.toolName })
continue
}

View File

@@ -47,11 +47,12 @@ export async function executePreCompactHooks(
let firstHookName: string | undefined
const collectedContext: string[] = []
for (const matcher of matchers) {
for (const hook of matcher.hooks) {
if (hook.type !== "command") continue
for (const matcher of matchers) {
if (!matcher.hooks || matcher.hooks.length === 0) continue
for (const hook of matcher.hooks) {
if (hook.type !== "command") continue
if (isHookCommandDisabled("PreCompact", hook.command, extendedConfig ?? null)) {
if (isHookCommandDisabled("PreCompact", hook.command, extendedConfig ?? null)) {
log("PreCompact hook command skipped (disabled by config)", { command: hook.command })
continue
}

View File

@@ -74,11 +74,12 @@ export async function executePreToolUseHooks(
let firstHookName: string | undefined
const inputLines = buildInputLines(ctx.toolInput)
for (const matcher of matchers) {
for (const hook of matcher.hooks) {
if (hook.type !== "command") continue
for (const matcher of matchers) {
if (!matcher.hooks || matcher.hooks.length === 0) continue
for (const hook of matcher.hooks) {
if (hook.type !== "command") continue
if (isHookCommandDisabled("PreToolUse", hook.command, extendedConfig ?? null)) {
if (isHookCommandDisabled("PreToolUse", hook.command, extendedConfig ?? null)) {
log("PreToolUse hook command skipped (disabled by config)", { command: hook.command, toolName: ctx.toolName })
continue
}

View File

@@ -65,11 +65,12 @@ export async function executeStopHooks(
hook_source: "opencode-plugin",
}
for (const matcher of matchers) {
for (const hook of matcher.hooks) {
if (hook.type !== "command") continue
for (const matcher of matchers) {
if (!matcher.hooks || matcher.hooks.length === 0) continue
for (const hook of matcher.hooks) {
if (hook.type !== "command") continue
if (isHookCommandDisabled("Stop", hook.command, extendedConfig ?? null)) {
if (isHookCommandDisabled("Stop", hook.command, extendedConfig ?? null)) {
log("Stop hook command skipped (disabled by config)", { command: hook.command })
continue
}

View File

@@ -70,9 +70,10 @@ export async function executeUserPromptSubmitHooks(
hook_source: "opencode-plugin",
}
for (const matcher of matchers) {
for (const hook of matcher.hooks) {
if (hook.type !== "command") continue
for (const matcher of matchers) {
if (!matcher.hooks || matcher.hooks.length === 0) continue
for (const hook of matcher.hooks) {
if (hook.type !== "command") continue
if (isHookCommandDisabled("UserPromptSubmit", hook.command, extendedConfig ?? null)) {
log("UserPromptSubmit hook command skipped (disabled by config)", { command: hook.command })