{"record":{"id":"4f6aa52f465625a8","repo":"donnemartin/interactive-coding-challenges","slug":"license-key-must-be-a-str","errorCode":null,"errorMessage":"license_key must be a str","messagePattern":"license_key must be a str","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"online_judges/license_key/format_license_key_solution.ipynb","lineNumber":120,"sourceCode":"  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Code\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 1,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"class Solution(object):\\n\",\n    \"\\n\",\n    \"    def format_license_key(self, license_key, k):\\n\",\n    \"        if license_key is None:\\n\",\n    \"            raise TypeError('license_key must be a str')\\n\",\n    \"        if not license_key:\\n\",\n    \"            raise ValueError('license_key must not be empty')\\n\",\n    \"        formatted_license_key = []\\n\",\n    \"        num_chars = 0\\n\",\n    \"        for char in license_key[::-1]:\\n\",\n    \"            if char == '-':\\n\",\n    \"                continue\\n\",\n    \"            num_chars += 1\\n\",\n    \"            formatted_license_key.append(char.upper())\\n\",\n    \"            if num_chars >= k:\\n\",\n    \"                formatted_license_key.append('-')\\n\",\n    \"                num_chars = 0\\n\",\n    \"        if formatted_license_key and formatted_license_key[-1] == '-':\\n\",\n    \"            formatted_license_key.pop(-1)\\n\",\n    \"        return ''.join(formatted_license_key[::-1])\"\n   ]\n  },\n  {","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/donnemartin/interactive-coding-challenges/blob/358f2cc60426d5c4c3d7d580910eec9a7b393fa9/online_judges/license_key/format_license_key_solution.ipynb#L102-L138","documentation":"Raised by Solution.format_license_key when license_key is None. The method iterates license_key[::-1]; None would fail with a confusing TypeError, so the guard demands a str up front (despite raising TypeError, the semantic check is 'must be a str').","triggerScenarios":"Calling format_license_key(None, k) — e.g. a config/env value never set, or a function parameter defaulting to None and passed through.","commonSituations":"Reading keys from config files or environment variables that are optional; tests asserting the None guard.","solutions":["Pass a non-empty string, e.g. format_license_key('2-4A0r7-4k', 4)","Default at the call site: key = key or '' and handle emptiness separately","Fix the source that yields None (missing env var, absent config key)"],"exampleFix":"# before\nsolution.format_license_key(os.environ.get('LICENSE_KEY'), 4)\n\n# after\nkey = os.environ.get('LICENSE_KEY') or '2-4A0r7-4k'\nsolution.format_license_key(key, 4)","handlingStrategy":"type-guard","validationCode":"if license_key is None: raise ValueError('license_key is required')\nsolution.format_license_key(license_key, k)","typeGuard":"def is_str(s): return isinstance(s, str)","tryCatchPattern":"try:\n    key = solution.format_license_key(raw, k)\nexcept TypeError:\n    key = solution.format_license_key(DEFAULT_KEY, k)","preventionTips":["Use `or default` for env/config strings","Coerce inputs with str() at boundaries when appropriate"],"tags":["python","input-validation","none-check","strings","formatting"],"backgroundTag":"none-argument-validation","analyzedSha":"358f2cc60426d5c4c3d7d580910eec9a7b393fa9","analyzedAt":"2026-08-28T10:16:54.480Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}