{"record":{"id":"cba316432501e8da","repo":"oraios/serena","slug":"tool-name-is-required-in-the-hook-input-data","errorCode":null,"errorMessage":"Tool name is required in the hook input data","messagePattern":"Tool name is required in the hook input data","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/serena/hooks.py","lineNumber":73,"sourceCode":"            \"read\",\n            \"diagnostics\",\n            \"memory\",\n            \"onboarding\",\n            \"config\",\n            \"list_file\",\n            \"find_file\",\n            \"shell\",\n            \"dashboard\",\n            \"restart_language_server\",\n        )\n    )\n\n    def __init__(self, client: HookClient):\n        super().__init__(client)\n        _tool_name = self._input_data.get(\"tool_name\") or self._input_data.get(\"toolName\", \"\") or \"\"\n        _tool_name = str(_tool_name).lower().strip()\n        if not _tool_name:\n            raise ValueError(\"Tool name is required in the hook input data\")\n        self._tool_name = _tool_name\n        raw_tool_input = self._input_data.get(\"tool_input\") or self._input_data.get(\"toolInput\")\n        # TODO: some agents, like copilot CLI, can send a string as value for raw_tool_input\n        #  Example: \"tool_input\":\"*** Begin Patch\\n*** Add File: /Users/acbdef/.copilot/session-state/08a961db-02f0-4c7c-b783-1e9818290292/files/hook-tool-test-3.txt\\n+third edit tool test\\n*** End Patch\\n\"\n        #  We currently don't parse such tool input and hence don't react to it in hooks\n        self._tool_input: dict | None = raw_tool_input if isinstance(raw_tool_input, dict) else None\n\n        # only relevant in claude code at the moment, (not all events include this field; default to empty string)\n        raw_permission_mode = self._input_data.get(\"permission_mode\") or self._input_data.get(\"permissionMode\") or \"\"\n        self._permission_mode = str(raw_permission_mode).strip()\n\n    @dataclass\n    class OutputData:\n        permission_decision: Literal[\"deny\", \"allow\"]\n        permission_decision_reason: str\n        additional_context: str = \"\"\n\n        def to_json_string(self, client: HookClient) -> str:","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/oraios/serena/blob/7fcbca7e62555ec2287ddb2f083caee805848ea6/src/serena/hooks.py#L55-L91","documentation":"ToolHook subclasses (e.g. pre/post-tool-use hooks) require the hook input to name the tool being triggered. __init__ reads tool_name/toolName, normalizes to lowercase, and raises ValueError if it is empty, because the hook cannot dispatch without knowing which tool fired.","triggerScenarios":"A hook event payload for a tool-based hook lacks tool_name/toolName or supplies an empty/whitespace string; custom hook clients that only forward tool_input.","commonSituations":"Custom agent integrations with incomplete hook payloads; schema drift between agent versions (toolName vs tool_name); hand-testing hook scripts with minimal JSON.","solutions":["Include a non-empty \"tool_name\" in the hook input JSON","Update the agent CLI/hook client so it forwards the tool name","If testing hooks manually, replicate the full payload shape the agent sends"],"exampleFix":"// before\n{\"session_id\": \"abc\", \"tool_input\": {\"path\": \"x.py\"}}\n// after\n{\"session_id\": \"abc\", \"tool_name\": \"read_file\", \"tool_input\": {\"path\": \"x.py\"}}","handlingStrategy":"validation","validationCode":"def validate_tool_hook(data: dict) -> str:\n    name = str(data.get(\"tool_name\") or data.get(\"toolName\") or \"\").lower().strip()\n    if not name:\n        raise ValueError(\"hook input JSON must include a non-empty tool_name\")\n    return name","typeGuard":null,"tryCatchPattern":"try:\n    hook = ToolHook(client)\nexcept ValueError as e:\n    if \"Tool name\" in str(e):\n        logging.error(\"Hook payload missing tool_name: check hook client schema\")\n    else:\n        raise","preventionTips":["Always send tool_name (and tool_input as a dict) in tool hook payloads","Keep the agent CLI and serena versions aligned","Add a unit test asserting the hook payload contains tool_name","Normalize field names (toolName vs tool_name) in custom clients"],"tags":["python","hooks","validation","config"],"backgroundTag":"missing-required-field","analyzedSha":"7fcbca7e62555ec2287ddb2f083caee805848ea6","analyzedAt":"2026-08-29T00:04:09.619Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}