{"record":{"id":"49e6ad2df8572a4d","repo":"TheAlgorithms/Python","slug":"key-must-be-a-string","errorCode":null,"errorMessage":"key must be a string","messagePattern":"key must be a string","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ciphers/autokey.py","lineNumber":41,"sourceCode":"        ...\n    TypeError: key must be a string\n    >>> encrypt(\"\", \"TheAlgorithms\")\n    Traceback (most recent call last):\n        ...\n    ValueError: plaintext is empty\n    >>> encrypt(\"coffee is good as python\", \"\")\n    Traceback (most recent call last):\n        ...\n    ValueError: key is empty\n    >>> encrypt(527.26, \"TheAlgorithms\")\n    Traceback (most recent call last):\n        ...\n    TypeError: plaintext must be a string\n    \"\"\"\n    if not isinstance(plaintext, str):\n        raise TypeError(\"plaintext must be a string\")\n    if not isinstance(key, str):\n        raise TypeError(\"key must be a string\")\n\n    if not plaintext:\n        raise ValueError(\"plaintext is empty\")\n    if not key:\n        raise ValueError(\"key is empty\")\n\n    key += plaintext\n    plaintext = plaintext.lower()\n    key = key.lower()\n    plaintext_iterator = 0\n    key_iterator = 0\n    ciphertext = \"\"\n    while plaintext_iterator < len(plaintext):\n        if (\n            ord(plaintext[plaintext_iterator]) < 97\n            or ord(plaintext[plaintext_iterator]) > 122\n        ):\n            ciphertext += plaintext[plaintext_iterator]","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/TheAlgorithms/Python/blob/f5988cc09713315817df6a7e327e258013a94440/ciphers/autokey.py#L23-L59","documentation":"Raised by autokey encrypt() when the key argument is not a str. Alongside the plaintext check, the function requires both operands to be strings because it concatenates key += plaintext and indexes both with ord() arithmetic.","triggerScenarios":"Calling encrypt('coffee is good as python', 2), or passing None/bytes/list as the key.","commonSituations":"Using a numeric key out of habit from Caesar/Vigenère examples, or swapping the argument order so a number lands in the key slot.","solutions":["Pass a string key: encrypt(text, str(2)) or better, an actual keyword like 'TheAlgorithms'.","If key arrives as bytes, decode it: key.decode('utf-8').","Remember the order: encrypt(plaintext, key) — plaintext first."],"exampleFix":"# before\nencrypt('hello', 2)  # TypeError: key must be a string\n\n# after\nencrypt('hello', 'coffee')","handlingStrategy":"type-guard","validationCode":"if not isinstance(key, str) or not key:\n    raise ValueError('a non-empty string key is required')","typeGuard":"def is_nonempty_str(v: object) -> bool:\n    return isinstance(v, str) and len(v) > 0","tryCatchPattern":null,"preventionTips":["Use keyword-style string keys ('TheAlgorithms'), never numeric keys.","Validate both operands once with a shared helper before encrypt/decrypt."],"tags":["cipher","type-error","python"],"backgroundTag":null,"analyzedSha":"f5988cc09713315817df6a7e327e258013a94440","analyzedAt":"2026-08-14T17:30:07.041Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}