{"record":{"id":"8eb713a7f446d9fb","repo":"pandas-dev/pandas","slug":"expected-hashable-got-type-col-name","errorCode":null,"errorMessage":"Expected Hashable, got: {type(col_name)}","messagePattern":"Expected Hashable, got: (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"pandas/core/col.py","lineNumber":413,"sourceCode":"    --------\n\n    You can use `col` in `assign`.\n\n    >>> df = pd.DataFrame({\"name\": [\"beluga\", \"narwhal\"], \"speed\": [100, 110]})\n    >>> df.assign(name_titlecase=pd.col(\"name\").str.title())\n          name  speed name_titlecase\n    0   beluga    100         Beluga\n    1  narwhal    110        Narwhal\n\n    You can also use it for filtering.\n\n    >>> df.loc[pd.col(\"speed\") > 105]\n          name  speed\n    1  narwhal    110\n    \"\"\"\n    if not isinstance(col_name, Hashable):\n        msg = f\"Expected Hashable, got: {type(col_name)}\"\n        raise TypeError(msg)\n\n    def func(df: DataFrame) -> Series:\n        if col_name not in df.columns:\n            columns_str = str(df.columns.tolist())\n            max_len = 90\n            if len(columns_str) > max_len:\n                columns_str = columns_str[:max_len] + \"...]\"\n\n            msg = (\n                f\"Column '{col_name}' not found in given DataFrame.\\n\\n\"\n                f\"Hint: did you mean one of {columns_str} instead?\"\n            )\n            raise ValueError(msg)\n        return df[col_name]\n\n    return Expression(func, f\"col({col_name!r})\")\n\n","sourceCodeStart":395,"sourceCodeEnd":431,"githubUrl":"https://github.com/pandas-dev/pandas/blob/71959b8cb9b2459c16e14b34f28b178ccfe14735/pandas/core/col.py#L395-L431","documentation":"Raised by pandas.col (pandas/core/col.py:413) when the `col_name` argument is not an instance of Hashable. pd.col stores the name for later deferred lookup against a DataFrame, so it must be a hashable label (str, int, tuple of hashables, etc.). Unhashable types like list, dict, or ndarray cannot serve as column keys and are rejected up front.","triggerScenarios":"`pd.col(['a','b'])` (passing a list), `pd.col({'x':1})`, `pd.col(np.array([1,2]))`, or any mutable/unhashable object. Also `pd.col(df)` where df is a DataFrame.","commonSituations":"Confusing pd.col (single deferred column) with multi-column selection. Passing a dynamic list computed at runtime without picking a single element.","solutions":["Pass a single hashable name: `pd.col('a')` or `pd.col(0)`.","For multiple columns, build separate Expressions: `[pd.col(c) for c in ['a','b']]`.","If you have a tuple column (MultiIndex level), pass the full tuple: `pd.col(('a','b'))`."],"exampleFix":"# before\npd.col(['speed','name'])\n\n# after\n[pd.col(c) for c in ['speed','name']]","handlingStrategy":"validation","validationCode":"from typing import Hashable\n\ndef safe_col(name):\n    if not isinstance(name, Hashable):\n        raise TypeError(f'col_name must be Hashable, got {type(name).__name__}')\n    import pandas as pd\n    return pd.col(name)","typeGuard":"from typing import Hashable\n\ndef is_hashable_name(name) -> bool:\n    try:\n        hash(name)\n        return isinstance(name, Hashable)\n    except TypeError:\n        return False","tryCatchPattern":"try:\n    expr = pd.col(name)\nexcept TypeError as e:\n    if 'Expected Hashable' in str(e):\n        name = name[0] if isinstance(name, (list, tuple)) and len(name) == 1 else name\n        expr = pd.col(name)\n    else:\n        raise","preventionTips":["Pass only a single hashable label (str, int, tuple) to pd.col.","For multiple columns, build a list of Expressions.","Validate dynamic names with isinstance(name, Hashable) first."],"tags":["expression","pd-col","hashable","validation","typeerror"],"analyzedSha":"71959b8cb9b2459c16e14b34f28b178ccfe14735","analyzedAt":"2026-08-07T01:30:20.476Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}