donnemartin/interactive-coding-challenges · error · TypeError

license_key must be a str

Error message

license_key must be a str

What it means

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').

Source

Thrown at online_judges/license_key/format_license_key_solution.ipynb:120

  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Code"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Solution(object):\n",
    "\n",
    "    def format_license_key(self, license_key, k):\n",
    "        if license_key is None:\n",
    "            raise TypeError('license_key must be a str')\n",
    "        if not license_key:\n",
    "            raise ValueError('license_key must not be empty')\n",
    "        formatted_license_key = []\n",
    "        num_chars = 0\n",
    "        for char in license_key[::-1]:\n",
    "            if char == '-':\n",
    "                continue\n",
    "            num_chars += 1\n",
    "            formatted_license_key.append(char.upper())\n",
    "            if num_chars >= k:\n",
    "                formatted_license_key.append('-')\n",
    "                num_chars = 0\n",
    "        if formatted_license_key and formatted_license_key[-1] == '-':\n",
    "            formatted_license_key.pop(-1)\n",
    "        return ''.join(formatted_license_key[::-1])"
   ]
  },
  {

View on GitHub (pinned to 358f2cc604)

Solutions

  1. Pass a non-empty string, e.g. format_license_key('2-4A0r7-4k', 4)
  2. Default at the call site: key = key or '' and handle emptiness separately
  3. Fix the source that yields None (missing env var, absent config key)

Example fix

# before
solution.format_license_key(os.environ.get('LICENSE_KEY'), 4)

# after
key = os.environ.get('LICENSE_KEY') or '2-4A0r7-4k'
solution.format_license_key(key, 4)
Defensive patterns

Strategy: type-guard

Validate before calling

if license_key is None: raise ValueError('license_key is required')
solution.format_license_key(license_key, k)

Type guard

def is_str(s): return isinstance(s, str)

Try / catch

try:
    key = solution.format_license_key(raw, k)
except TypeError:
    key = solution.format_license_key(DEFAULT_KEY, k)

Prevention

When it happens

Trigger: Calling format_license_key(None, k) — e.g. a config/env value never set, or a function parameter defaulting to None and passed through.

Common situations: Reading keys from config files or environment variables that are optional; tests asserting the None guard.

Related errors


AI-assisted analysis of donnemartin/interactive-coding-challenges@358f2cc604 (2026-08-28). Data as JSON: /api/errors/4f6aa52f465625a8. Report an issue: GitHub.