{"record":{"id":"26a34bc749d47613","repo":"crewAIInc/crewAI","slug":"invalid-distance-metric-metric","errorCode":null,"errorMessage":"Invalid distance metric: {metric}","messagePattern":"Invalid distance metric: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"lib/crewai-tools/src/crewai_tools/tools/db2_search_tool/db2_search_tool.py","lineNumber":293,"sourceCode":"                indent=2,\n            )\n\n        try:\n            query_vector = self._generate_embedding(query)\n\n            # Explicit Connection Handling\n            try:\n                self._connect()\n            except Exception as e:\n                self._disconnect()  # Clean up any partial connection\n                return json.dumps(\n                    {\"success\": False, \"error\": f\"Failed to connect to DB2: {e!s}\"}\n                )\n\n            # Validate Metric\n            metric = self.distance_metric.upper()\n            if metric not in self._ALLOWED_METRICS:\n                raise ValueError(f\"Invalid distance metric: {metric}\")\n\n            # Validate Identifiers\n            table = self._validate_identifier(self.table_name, allow_period=True)\n            v_col = self._validate_identifier(self.vector_column)\n            ret_cols = [self._validate_identifier(c) for c in self.return_columns]\n\n            vector_dimension = len(query_vector)\n            vector_string = str(query_vector)\n\n            filter_clause = \"\"\n            params = [vector_string]  # The vector string for the CLOB cast\n\n            if filter_by and filter_value is not None:\n                f_col = self._validate_identifier(filter_by)\n                filter_clause = f\"WHERE {f_col} = ?\"\n                params.append(filter_value)\n\n            # DYNAMIC COLUMN SELECTION","sourceCodeStart":275,"sourceCodeEnd":311,"githubUrl":"https://github.com/crewAIInc/crewAI/blob/754d7323beb2fd042e33444a115ea2d5a47193f0/lib/crewai-tools/src/crewai_tools/tools/db2_search_tool/db2_search_tool.py#L275-L311","documentation":"During _run, after connecting, DB2VectorSearchTool uppercases self.distance_metric and checks membership in self._ALLOWED_METRICS; anything else raises ValueError(f\"Invalid distance metric: {metric}\"). The allowlist exists because the metric is interpolated into the SQL distance function (e.g. VECTOR_COSINE/COSINE family), so arbitrary strings are both invalid and unsafe. The connection is already open when this fires, but no query has run.","triggerScenarios":"DB2VectorSearchTool(..., distance_metric='manhattan') or 'dot' or 'euclidian' (typo) or 'cosine distance'; passing the metric with extra whitespace; assuming an abbreviation like 'l2' is supported.","commonSituations":"Porting code from another vector DB (pgvector, Pinecone) whose metric names differ; LLM-configured tools guessing metric names; typos and case variants (case is actually normalized, so only the name itself matters).","solutions":["Use one of the allowed metric strings — check DB2VectorSearchTool._ALLOWED_METRICS for the installed version; typically 'COSINE', 'EUCLIDEAN', 'DOT' style names (e.g. distance_metric='COSINE').","Print the allowlist once: print(DB2VectorSearchTool._ALLOWED_METRICS) to see exact accepted values.","Guard configuration by validating distance_metric.upper() in _ALLOWED_METRICS before constructing the tool."],"exampleFix":"# before\ntool = DB2VectorSearchTool(table_name='docs', vector_column='embedding', return_columns=['id'], distance_metric='manhattan')\n\n# after\ntool = DB2VectorSearchTool(table_name='docs', vector_column='embedding', return_columns=['id'], distance_metric='EUCLIDEAN')","handlingStrategy":"validation","validationCode":"metric = (distance_metric or 'COSINE').strip().upper()\nif metric not in DB2VectorSearchTool._ALLOWED_METRICS:\n    raise ValueError(f'Invalid distance metric: {metric}; allowed: {DB2VectorSearchTool._ALLOWED_METRICS}')\ntool = DB2VectorSearchTool(..., distance_metric=metric)","typeGuard":"def is_allowed_metric(value: object) -> bool:\n    return isinstance(value, str) and value.strip().upper() in DB2VectorSearchTool._ALLOWED_METRICS","tryCatchPattern":"try:\n    tool._run(query_vector=vec, query_text=q)\nexcept ValueError as e:\n    if 'Invalid distance metric' in str(e):\n        tool.distance_metric = 'COSINE'  # fall back to default and retry\n        tool._run(query_vector=vec, query_text=q)\n    else:\n        raise","preventionTips":["Print DB2VectorSearchTool._ALLOWED_METRICS once and copy exact strings into config.","Normalize case/whitespace on the metric before constructing the tool.","Make the metric an Enum in your config layer so only valid names compile/load."],"tags":["db2","validation","distance-metric","vector-search","configuration"],"backgroundTag":null,"analyzedSha":"754d7323beb2fd042e33444a115ea2d5a47193f0","analyzedAt":"2026-08-15T04:06:56.746Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}