{"record":{"id":"4e2cb6269ef0330d","repo":"Hmbown/CodeWhale","slug":"disabled-tools-must-use-codewhale-catalog-identifi","errorCode":null,"errorMessage":"disabled_tools must use Codewhale catalog identifiers: ${\", \".join(repr(tool) for tool in invalid)}","messagePattern":"disabled_tools must use Codewhale catalog identifiers: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"integrations/verifiers-codewhale/codewhale_harness/harness.py","lineNumber":110,"sourceCode":"    APPENDS_SYSTEM_PROMPT = True\n    SUPPORTS_MCP = True\n    SUPPORTS_USER_SIM = False\n\n    def _validate_config(self) -> None:\n        if not _VERSION.fullmatch(self.config.version):\n            raise ValueError(\"version must be a semantic release identifier\")\n        if (\n            self.config.max_turns is not None\n            and not 1 <= self.config.max_turns <= 10_000\n        ):\n            raise ValueError(\"max_turns must be between 1 and 10000\")\n        invalid = [\n            tool\n            for tool in self.config.disabled_tools or []\n            if not _TOOL.fullmatch(tool)\n        ]\n        if invalid:\n            raise ValueError(\n                \"disabled_tools must use Codewhale catalog identifiers: \"\n                + \", \".join(repr(tool) for tool in invalid)\n            )\n\n    @property\n    def binary(self) -> str:\n        configured = (self.config.binary_path or \"\").strip()\n        return configured or DEFAULT_BINARY\n\n    async def setup(self, runtime: Runtime) -> None:\n        self._validate_config()\n        if self.config.binary_path:\n            logger.info(\"codewhale: verifying preinstalled %s\", self.binary)\n            result = await runtime.run([self.binary, \"--version\"], {})\n            version_text = f\"{result.stdout}\\n{result.stderr}\"\n            if result.exit_code != 0 or not _has_version(\n                version_text, self.config.version\n            ):","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/integrations/verifiers-codewhale/codewhale_harness/harness.py#L92-L128","documentation":"Every entry in config.disabled_tools must fullmatch ^[a-z0-9][a-z0-9_-]*$ — a lowercase Codewhale catalog identifier starting with an alphanumeric. The offending entries are interpolated into the message with repr(), so the error names exactly which strings failed. The list is joined into --disallowed-tools on the exec command line, so uppercase, spaces, dots, or a leading dash break the CLI contract.","triggerScenarios":"disabled_tools=['Bash'], ['read file'], ['-grep'], or dotted names like ['fs.read_file'].","commonSituations":"Copying display names from another agent CLI; mixing glob patterns or module-qualified ids into the list; case-changing config merges.","solutions":["Use exact catalog identifiers: lowercase letters, digits, underscores, hyphens","List the tool catalog with the binary's tool-listing command and copy names verbatim","Filter entries through the same regex before building the config"],"exampleFix":"# before\nconfig = CodewhaleHarnessConfig(version='0.9.1', disabled_tools=['Bash', 'Read File'])\n# after\nconfig = CodewhaleHarnessConfig(version='0.9.1', disabled_tools=['bash', 'read_file'])","handlingStrategy":"type-guard","validationCode":"import re\n_TOOL = re.compile(r'^[a-z0-9][a-z0-9_-]*$')\ntools = [t for t in configured_tools if _TOOL.fullmatch(t)]\nconfig = CodewhaleHarnessConfig(version='0.9.1', disabled_tools=tools)","typeGuard":"import re\n_TOOL = re.compile(r'^[a-z0-9][a-z0-9_-]*$')\n\ndef valid_tool_id(t):\n    return isinstance(t, str) and _TOOL.fullmatch(t) is not None","tryCatchPattern":null,"preventionTips":["Source tool names from the binary's catalog listing, not prose","Lowercase and strip whitespace at ingestion","Reject dotted or glob-form ids early in config loading"],"tags":["config","validation","python","tools","harness"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}