{"record":{"id":"96b6c7bdc6add0ea","repo":"TheAlgorithms/Python","slug":"var-name-all-keys-must-be-strings","errorCode":null,"errorMessage":"{var_name} all keys must be strings","messagePattern":"(.+?) all keys must be strings","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"dynamic_programming/viterbi.py","lineNumber":367,"sourceCode":"    >>> _validate_dict({\"a\": 8}, \"mock_name\", dict)\n    Traceback (most recent call last):\n            ...\n    ValueError: mock_name all values must be dict\n    >>> _validate_dict({2: 0.5}, \"mock_name\",float, True)\n    Traceback (most recent call last):\n            ...\n    ValueError: mock_name all keys must be strings\n    >>> _validate_dict({\"b\": 4}, \"mock_name\", float,True)\n    Traceback (most recent call last):\n            ...\n    ValueError: mock_name nested dictionary all values must be float\n    \"\"\"\n    if not isinstance(_object, dict):\n        msg = f\"{var_name} must be a dict\"\n        raise ValueError(msg)\n    if not all(isinstance(x, str) for x in _object):\n        msg = f\"{var_name} all keys must be strings\"\n        raise ValueError(msg)\n    if not all(isinstance(x, value_type) for x in _object.values()):\n        nested_text = \"nested dictionary \" if nested else \"\"\n        msg = f\"{var_name} {nested_text}all values must be {value_type.__name__}\"\n        raise ValueError(msg)\n\n\nif __name__ == \"__main__\":\n    from doctest import testmod\n\n    testmod()\n","sourceCodeStart":349,"sourceCodeEnd":378,"githubUrl":"https://github.com/TheAlgorithms/Python/blob/f5988cc09713315817df6a7e327e258013a94440/dynamic_programming/viterbi.py#L349-L378","documentation":"Raised by viterbi's _validate_dict when the object is a dict but one or more keys is not a string. Probability tables are keyed by state and observation names (symbols), so integer or float keys like {2: 0.5} are rejected. The same validator runs on nested dicts (rows of the transition/emission tables) with nested=True.","triggerScenarios":"Passing initial_probabilities={0: 0.6, 1: 0.4} with integer state codes; a transition row {'rainy': {0: 0.7}}; keys loaded from JSON where someone used numeric ids as object keys and they stayed ints after processing.","commonSituations":"Building HMM tables programmatically with enumerate() ints as keys; converting from a matrix representation where indices leak into dict keys; mixing a string state list with numeric-keyed probability tables (the two never match).","solutions":["Key every probability dict by the string state/symbol names used in states_space and observations_space: {'rainy': 0.6, 'sunny': 0.4}.","When converting from matrix indices, map through the names: {states[i]: {states[j]: m[i][j] ...}}.","Add a self-check that set(initial_probabilities) == set(states_space)."],"exampleFix":"# before\ninitial_p = {0: 0.6, 1: 0.4}  # ValueError: keys must be strings\n\n# after\nstates = ['rainy', 'sunny']\ninitial_p = {'rainy': 0.6, 'sunny': 0.4}","handlingStrategy":"validation","validationCode":"def keys_match(table: dict, names: list[str]) -> bool:\n    return all(isinstance(k, str) for k in table) and set(table) == set(names)","typeGuard":"def str_keyed(d: object) -> TypeGuard[dict[str, object]]:\n    return isinstance(d, dict) and all(isinstance(k, str) for k in d)","tryCatchPattern":null,"preventionTips":["Build tables via {states[i]: ...} so names, not indices, become keys.","Assert set(initial_probabilities) == set(states_space) in tests.","Avoid numeric keys surviving from matrix-to-dict conversions."],"tags":["dynamic-programming","hmm","type-validation"],"backgroundTag":null,"analyzedSha":"f5988cc09713315817df6a7e327e258013a94440","analyzedAt":"2026-08-14T17:30:07.041Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}