[BUG] hookify rule files containing non-ASCII are silently skipped on Windows (open() without encoding)

Status Open
Reported on v2.1.238
Maintainer reply None cached
Activity 1 comment · opened Aug 23, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

plugins/hookify/core/config_loader.py opens rule files with open(file_path, 'r') and no encoding, so Python uses the locale default. On Windows that is cp1252, and a rule file containing any byte cp1252 cannot map raises UnicodeDecodeError. That subclasses ValueError, so it is swallowed by the except (ValueError, KeyError, AttributeError, TypeError) handler in load_rule_file, which returns None. The rule is dropped and the hook proceeds.

This defeats action: block rules. The plugin's own shipped examples/dangerous-rm.local.md contains a warning emoji (e2 9a a0 ef b8 8f), so following the documented example produces a block rule that never blocks.

This is separate from #81448, and it affects the copy in this repo and the one in anthropics/claude-plugins-official equally; neither passes an encoding.

What Should Happen?

Rule files should be read as UTF-8 regardless of platform locale, so a rule containing non-ASCII characters loads and is enforced.

Error Messages/Logs

Error: Malformed rule file .claude\hookify.dangerous-rm.local.md: 'charmap' codec can't decode byte 0x8f in position 97: character maps to <undefined>

This goes to stderr. stdout carries no indication that a rule was dropped.

Steps to Reproduce

  1. Copy the plugin's own example in as a rule: plugins/hookify/examples/dangerous-rm.local.md to <project>/.claude/hookify.dangerous-rm.local.md. It is action: block on pattern rm\s+-rf.
  2. On Windows, feed a matching PreToolUse payload to the hook script:

``
{"hook_event_name":"PreToolUse","tool_name":"Bash","tool_input":{"command":"rm -rf /"},"cwd":"<project>","session_id":"t"}
``

  1. Observed: stdout is {}, so the command is allowed. stderr shows the charmap error above.
  2. Change core/config_loader.py:251 to open(file_path, 'r', encoding='utf-8') and repeat.
  3. Observed: {"hookSpecificOutput": {"hookEventName": "PreToolUse", "permissionDecision": "deny"}, ...} and the rule fires as documented.

This reproduces where the locale default is not UTF-8. On macOS/Linux with a UTF-8 locale it does not, which is likely why it has gone unreported.

Claude Model

Not sure / Multiple models

Is this a regression?

I don't know

Claude Code Version

2.1.238

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

Other

Additional Information

Python 3.13, locale.getpreferredencoding(False) returns cp1252. Python 3.15 makes UTF-8 mode the default (PEP 686), which would mask this. hookify 0.1.0, installed from the claude-code-plugins marketplace.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗